Move resolved usernames to DialogManager.
This commit is contained in:
parent
dc3929fede
commit
a2c6f4aa7c
@ -13,7 +13,6 @@
|
|||||||
#include "td/telegram/Global.h"
|
#include "td/telegram/Global.h"
|
||||||
#include "td/telegram/LinkManager.h"
|
#include "td/telegram/LinkManager.h"
|
||||||
#include "td/telegram/MessageId.h"
|
#include "td/telegram/MessageId.h"
|
||||||
#include "td/telegram/MessagesManager.h"
|
|
||||||
#include "td/telegram/OptionManager.h"
|
#include "td/telegram/OptionManager.h"
|
||||||
#include "td/telegram/ServerMessageId.h"
|
#include "td/telegram/ServerMessageId.h"
|
||||||
#include "td/telegram/Td.h"
|
#include "td/telegram/Td.h"
|
||||||
@ -437,7 +436,7 @@ void BoostManager::get_dialog_boost_link_info(Slice url, Promise<DialogBoostLink
|
|||||||
auto info = r_dialog_boost_link_info.move_as_ok();
|
auto info = r_dialog_boost_link_info.move_as_ok();
|
||||||
auto query_promise = PromiseCreator::lambda(
|
auto query_promise = PromiseCreator::lambda(
|
||||||
[info, promise = std::move(promise)](Result<DialogId> &&result) mutable { promise.set_value(std::move(info)); });
|
[info, promise = std::move(promise)](Result<DialogId> &&result) mutable { promise.set_value(std::move(info)); });
|
||||||
td_->messages_manager_->resolve_dialog(info.username, info.channel_id, std::move(query_promise));
|
td_->dialog_manager_->resolve_dialog(info.username, info.channel_id, std::move(query_promise));
|
||||||
}
|
}
|
||||||
|
|
||||||
td_api::object_ptr<td_api::chatBoostLinkInfo> BoostManager::get_chat_boost_link_info_object(
|
td_api::object_ptr<td_api::chatBoostLinkInfo> BoostManager::get_chat_boost_link_info_object(
|
||||||
@ -446,7 +445,7 @@ td_api::object_ptr<td_api::chatBoostLinkInfo> BoostManager::get_chat_boost_link_
|
|||||||
|
|
||||||
bool is_public = !info.username.empty();
|
bool is_public = !info.username.empty();
|
||||||
DialogId dialog_id =
|
DialogId dialog_id =
|
||||||
is_public ? td_->messages_manager_->resolve_dialog_username(info.username) : DialogId(info.channel_id);
|
is_public ? td_->dialog_manager_->get_resolved_dialog_by_username(info.username) : DialogId(info.channel_id);
|
||||||
return td_api::make_object<td_api::chatBoostLinkInfo>(
|
return td_api::make_object<td_api::chatBoostLinkInfo>(
|
||||||
is_public, td_->dialog_manager_->get_chat_id_object(dialog_id, "chatBoostLinkInfo"));
|
is_public, td_->dialog_manager_->get_chat_id_object(dialog_id, "chatBoostLinkInfo"));
|
||||||
}
|
}
|
||||||
|
@ -12726,7 +12726,7 @@ void ContactsManager::update_user(User *u, UserId user_id, bool from_binlog, boo
|
|||||||
td_->inline_queries_manager_->remove_recent_inline_bot(user_id, Promise<>());
|
td_->inline_queries_manager_->remove_recent_inline_bot(user_id, Promise<>());
|
||||||
}
|
}
|
||||||
if (from_binlog || from_database) {
|
if (from_binlog || from_database) {
|
||||||
td_->messages_manager_->on_dialog_usernames_received(DialogId(user_id), u->usernames, true);
|
td_->dialog_manager_->on_dialog_usernames_received(DialogId(user_id), u->usernames, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
LOG(DEBUG) << "Update " << user_id << ": need_save_to_database = " << u->need_save_to_database
|
LOG(DEBUG) << "Update " << user_id << ": need_save_to_database = " << u->need_save_to_database
|
||||||
@ -13019,7 +13019,7 @@ void ContactsManager::update_channel(Channel *c, ChannelId channel_id, bool from
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (from_binlog || from_database) {
|
if (from_binlog || from_database) {
|
||||||
td_->messages_manager_->on_dialog_usernames_received(DialogId(channel_id), c->usernames, true);
|
td_->dialog_manager_->on_dialog_usernames_received(DialogId(channel_id), c->usernames, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!is_channel_public(c) && !c->has_linked_channel) {
|
if (!is_channel_public(c) && !c->has_linked_channel) {
|
||||||
@ -14132,6 +14132,7 @@ void ContactsManager::on_update_user_name(User *u, UserId user_id, string &&firs
|
|||||||
|
|
||||||
void ContactsManager::on_update_user_usernames(User *u, UserId user_id, Usernames &&usernames) {
|
void ContactsManager::on_update_user_usernames(User *u, UserId user_id, Usernames &&usernames) {
|
||||||
if (u->usernames != usernames) {
|
if (u->usernames != usernames) {
|
||||||
|
td_->dialog_manager_->on_dialog_usernames_updated(DialogId(user_id), u->usernames, usernames);
|
||||||
td_->messages_manager_->on_dialog_usernames_updated(DialogId(user_id), u->usernames, usernames);
|
td_->messages_manager_->on_dialog_usernames_updated(DialogId(user_id), u->usernames, usernames);
|
||||||
if (u->can_be_edited_bot && u->usernames.get_editable_username() != usernames.get_editable_username()) {
|
if (u->can_be_edited_bot && u->usernames.get_editable_username() != usernames.get_editable_username()) {
|
||||||
u->is_full_info_changed = true;
|
u->is_full_info_changed = true;
|
||||||
@ -14141,7 +14142,7 @@ void ContactsManager::on_update_user_usernames(User *u, UserId user_id, Username
|
|||||||
LOG(DEBUG) << "Usernames have changed for " << user_id;
|
LOG(DEBUG) << "Usernames have changed for " << user_id;
|
||||||
u->is_changed = true;
|
u->is_changed = true;
|
||||||
} else if (u->is_bot || !td_->auth_manager_->is_bot()) {
|
} else if (u->is_bot || !td_->auth_manager_->is_bot()) {
|
||||||
td_->messages_manager_->on_dialog_usernames_received(DialogId(user_id), usernames, false);
|
td_->dialog_manager_->on_dialog_usernames_received(DialogId(user_id), usernames, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -17381,6 +17382,7 @@ void ContactsManager::on_update_channel_usernames(ChannelId channel_id, Username
|
|||||||
|
|
||||||
void ContactsManager::on_update_channel_usernames(Channel *c, ChannelId channel_id, Usernames &&usernames) {
|
void ContactsManager::on_update_channel_usernames(Channel *c, ChannelId channel_id, Usernames &&usernames) {
|
||||||
if (c->usernames != usernames) {
|
if (c->usernames != usernames) {
|
||||||
|
td_->dialog_manager_->on_dialog_usernames_updated(DialogId(channel_id), c->usernames, usernames);
|
||||||
td_->messages_manager_->on_dialog_usernames_updated(DialogId(channel_id), c->usernames, usernames);
|
td_->messages_manager_->on_dialog_usernames_updated(DialogId(channel_id), c->usernames, usernames);
|
||||||
if (c->is_update_supergroup_sent) {
|
if (c->is_update_supergroup_sent) {
|
||||||
on_channel_usernames_changed(c, channel_id, c->usernames, usernames);
|
on_channel_usernames_changed(c, channel_id, c->usernames, usernames);
|
||||||
@ -17390,7 +17392,7 @@ void ContactsManager::on_update_channel_usernames(Channel *c, ChannelId channel_
|
|||||||
c->is_username_changed = true;
|
c->is_username_changed = true;
|
||||||
c->is_changed = true;
|
c->is_changed = true;
|
||||||
} else {
|
} else {
|
||||||
td_->messages_manager_->on_dialog_usernames_received(DialogId(channel_id), usernames, false);
|
td_->dialog_manager_->on_dialog_usernames_received(DialogId(channel_id), usernames, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -23,6 +23,7 @@
|
|||||||
#include "td/telegram/Td.h"
|
#include "td/telegram/Td.h"
|
||||||
#include "td/telegram/UpdatesManager.h"
|
#include "td/telegram/UpdatesManager.h"
|
||||||
#include "td/telegram/UserId.h"
|
#include "td/telegram/UserId.h"
|
||||||
|
#include "td/telegram/Usernames.h"
|
||||||
|
|
||||||
#include "td/utils/algorithm.h"
|
#include "td/utils/algorithm.h"
|
||||||
#include "td/utils/buffer.h"
|
#include "td/utils/buffer.h"
|
||||||
@ -32,6 +33,43 @@
|
|||||||
|
|
||||||
namespace td {
|
namespace td {
|
||||||
|
|
||||||
|
class ResolveUsernameQuery final : public Td::ResultHandler {
|
||||||
|
Promise<Unit> promise_;
|
||||||
|
string username_;
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit ResolveUsernameQuery(Promise<Unit> &&promise) : promise_(std::move(promise)) {
|
||||||
|
}
|
||||||
|
|
||||||
|
void send(const string &username) {
|
||||||
|
username_ = username;
|
||||||
|
send_query(G()->net_query_creator().create(telegram_api::contacts_resolveUsername(username)));
|
||||||
|
}
|
||||||
|
|
||||||
|
void on_result(BufferSlice packet) final {
|
||||||
|
auto result_ptr = fetch_result<telegram_api::contacts_resolveUsername>(packet);
|
||||||
|
if (result_ptr.is_error()) {
|
||||||
|
return on_error(result_ptr.move_as_error());
|
||||||
|
}
|
||||||
|
|
||||||
|
auto ptr = result_ptr.move_as_ok();
|
||||||
|
LOG(DEBUG) << "Receive result for ResolveUsernameQuery: " << to_string(ptr);
|
||||||
|
td_->contacts_manager_->on_get_users(std::move(ptr->users_), "ResolveUsernameQuery");
|
||||||
|
td_->contacts_manager_->on_get_chats(std::move(ptr->chats_), "ResolveUsernameQuery");
|
||||||
|
|
||||||
|
td_->dialog_manager_->on_resolved_username(username_, DialogId(ptr->peer_));
|
||||||
|
|
||||||
|
promise_.set_value(Unit());
|
||||||
|
}
|
||||||
|
|
||||||
|
void on_error(Status status) final {
|
||||||
|
if (status.message() == Slice("USERNAME_NOT_OCCUPIED")) {
|
||||||
|
td_->dialog_manager_->drop_username(username_);
|
||||||
|
}
|
||||||
|
promise_.set_error(std::move(status));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
class EditDialogTitleQuery final : public Td::ResultHandler {
|
class EditDialogTitleQuery final : public Td::ResultHandler {
|
||||||
Promise<Unit> promise_;
|
Promise<Unit> promise_;
|
||||||
DialogId dialog_id_;
|
DialogId dialog_id_;
|
||||||
@ -381,6 +419,11 @@ DialogManager::DialogManager(Td *td, ActorShared<> parent) : td_(td), parent_(st
|
|||||||
upload_dialog_photo_callback_ = std::make_shared<UploadDialogPhotoCallback>();
|
upload_dialog_photo_callback_ = std::make_shared<UploadDialogPhotoCallback>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DialogManager::~DialogManager() {
|
||||||
|
Scheduler::instance()->destroy_on_scheduler(G()->get_gc_scheduler_id(), resolved_usernames_,
|
||||||
|
inaccessible_resolved_usernames_);
|
||||||
|
}
|
||||||
|
|
||||||
void DialogManager::tear_down() {
|
void DialogManager::tear_down() {
|
||||||
parent_.reset();
|
parent_.reset();
|
||||||
}
|
}
|
||||||
@ -1584,4 +1627,205 @@ bool DialogManager::is_dialog_removed_from_dialog_list(DialogId dialog_id) const
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DialogManager::on_dialog_usernames_updated(DialogId dialog_id, const Usernames &old_usernames,
|
||||||
|
const Usernames &new_usernames) {
|
||||||
|
LOG(INFO) << "Update usernames in " << dialog_id << " from " << old_usernames << " to " << new_usernames;
|
||||||
|
|
||||||
|
for (auto &username : old_usernames.get_active_usernames()) {
|
||||||
|
auto cleaned_username = clean_username(username);
|
||||||
|
resolved_usernames_.erase(cleaned_username);
|
||||||
|
inaccessible_resolved_usernames_.erase(cleaned_username);
|
||||||
|
}
|
||||||
|
|
||||||
|
on_dialog_usernames_received(dialog_id, new_usernames, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DialogManager::on_dialog_usernames_received(DialogId dialog_id, const Usernames &usernames, bool from_database) {
|
||||||
|
for (auto &username : usernames.get_active_usernames()) {
|
||||||
|
auto cleaned_username = clean_username(username);
|
||||||
|
if (!cleaned_username.empty()) {
|
||||||
|
resolved_usernames_[cleaned_username] =
|
||||||
|
ResolvedUsername{dialog_id, Time::now() + (from_database ? 0 : USERNAME_CACHE_EXPIRE_TIME)};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void DialogManager::send_resolve_dialog_username_query(const string &username, Promise<Unit> &&promise) {
|
||||||
|
td_->create_handler<ResolveUsernameQuery>(std::move(promise))->send(username);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DialogManager::resolve_dialog(const string &username, ChannelId channel_id, Promise<DialogId> promise) {
|
||||||
|
CHECK(username.empty() == channel_id.is_valid());
|
||||||
|
|
||||||
|
bool have_dialog = username.empty() ? td_->contacts_manager_->have_channel_force(channel_id, "resolve_dialog")
|
||||||
|
: get_resolved_dialog_by_username(username).is_valid();
|
||||||
|
if (!have_dialog) {
|
||||||
|
auto query_promise = PromiseCreator::lambda(
|
||||||
|
[actor_id = actor_id(this), username, channel_id, promise = std::move(promise)](Result<Unit> &&result) mutable {
|
||||||
|
if (result.is_error()) {
|
||||||
|
return promise.set_error(result.move_as_error());
|
||||||
|
}
|
||||||
|
send_closure(actor_id, &DialogManager::on_resolve_dialog, username, channel_id, std::move(promise));
|
||||||
|
});
|
||||||
|
if (username.empty()) {
|
||||||
|
td_->contacts_manager_->reload_channel(channel_id, std::move(query_promise), "resolve_dialog");
|
||||||
|
} else {
|
||||||
|
send_resolve_dialog_username_query(username, std::move(query_promise));
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
return on_resolve_dialog(username, channel_id, std::move(promise));
|
||||||
|
}
|
||||||
|
|
||||||
|
void DialogManager::on_resolve_dialog(const string &username, ChannelId channel_id, Promise<DialogId> &&promise) {
|
||||||
|
TRY_STATUS_PROMISE(promise, G()->close_status());
|
||||||
|
|
||||||
|
DialogId dialog_id;
|
||||||
|
if (username.empty()) {
|
||||||
|
if (!td_->contacts_manager_->have_channel(channel_id)) {
|
||||||
|
return promise.set_error(Status::Error(500, "Chat info not found"));
|
||||||
|
}
|
||||||
|
|
||||||
|
dialog_id = DialogId(channel_id);
|
||||||
|
force_create_dialog(dialog_id, "on_resolve_dialog");
|
||||||
|
} else {
|
||||||
|
dialog_id = get_resolved_dialog_by_username(username);
|
||||||
|
if (dialog_id.is_valid()) {
|
||||||
|
force_create_dialog(dialog_id, "on_resolve_dialog", true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!have_dialog_force(dialog_id, "on_resolve_dialog")) {
|
||||||
|
return promise.set_error(Status::Error(500, "Chat not found"));
|
||||||
|
}
|
||||||
|
promise.set_value(std::move(dialog_id));
|
||||||
|
}
|
||||||
|
|
||||||
|
DialogId DialogManager::get_resolved_dialog_by_username(const string &username) const {
|
||||||
|
auto cleaned_username = clean_username(username);
|
||||||
|
auto resolved_username = resolved_usernames_.get(cleaned_username);
|
||||||
|
if (resolved_username.dialog_id.is_valid()) {
|
||||||
|
return resolved_username.dialog_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
return inaccessible_resolved_usernames_.get(cleaned_username);
|
||||||
|
}
|
||||||
|
|
||||||
|
DialogId DialogManager::resolve_dialog_username(const string &username, Promise<Unit> &promise) {
|
||||||
|
auto resolved_username = resolved_usernames_.get(username);
|
||||||
|
if (resolved_username.dialog_id.is_valid()) {
|
||||||
|
if (resolved_username.expires_at < Time::now()) {
|
||||||
|
send_resolve_dialog_username_query(username, Promise<Unit>());
|
||||||
|
}
|
||||||
|
return resolved_username.dialog_id;
|
||||||
|
} else {
|
||||||
|
auto dialog_id = inaccessible_resolved_usernames_.get(username);
|
||||||
|
if (!dialog_id.is_valid()) {
|
||||||
|
send_resolve_dialog_username_query(username, std::move(promise));
|
||||||
|
}
|
||||||
|
return dialog_id;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DialogId DialogManager::search_public_dialog(const string &username_to_search, bool force, Promise<Unit> &&promise) {
|
||||||
|
string username = clean_username(username_to_search);
|
||||||
|
if (username[0] == '@') {
|
||||||
|
username = username.substr(1);
|
||||||
|
}
|
||||||
|
if (username.empty()) {
|
||||||
|
promise.set_error(Status::Error(200, "Username is invalid"));
|
||||||
|
return DialogId();
|
||||||
|
}
|
||||||
|
|
||||||
|
DialogId dialog_id;
|
||||||
|
auto resolved_username = resolved_usernames_.get(username);
|
||||||
|
if (resolved_username.dialog_id.is_valid()) {
|
||||||
|
if (resolved_username.expires_at < Time::now()) {
|
||||||
|
send_resolve_dialog_username_query(username, Promise<Unit>());
|
||||||
|
}
|
||||||
|
dialog_id = resolved_username.dialog_id;
|
||||||
|
} else {
|
||||||
|
dialog_id = inaccessible_resolved_usernames_.get(username);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dialog_id.is_valid()) {
|
||||||
|
if (have_input_peer(dialog_id, AccessRights::Read)) {
|
||||||
|
if (!force && reload_voice_chat_on_search_usernames_.count(username)) {
|
||||||
|
reload_voice_chat_on_search_usernames_.erase(username);
|
||||||
|
if (dialog_id.get_type() == DialogType::Channel) {
|
||||||
|
td_->contacts_manager_->reload_channel_full(dialog_id.get_channel_id(), std::move(promise),
|
||||||
|
"search_public_dialog");
|
||||||
|
return DialogId();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
td_->messages_manager_->create_dialog(dialog_id, false, std::move(promise));
|
||||||
|
return dialog_id;
|
||||||
|
} else {
|
||||||
|
// bot username may be known despite there is no access_hash
|
||||||
|
if (force || dialog_id.get_type() != DialogType::User) {
|
||||||
|
force_create_dialog(dialog_id, "search_public_dialog", true);
|
||||||
|
promise.set_value(Unit());
|
||||||
|
return dialog_id;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
send_resolve_dialog_username_query(username, std::move(promise));
|
||||||
|
return DialogId();
|
||||||
|
}
|
||||||
|
|
||||||
|
void DialogManager::reload_voice_chat_on_search(const string &username) {
|
||||||
|
if (!td_->auth_manager_->is_authorized()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto cleaned_username = clean_username(username);
|
||||||
|
if (!cleaned_username.empty()) {
|
||||||
|
reload_voice_chat_on_search_usernames_.insert(cleaned_username);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void DialogManager::on_resolved_username(const string &username, DialogId dialog_id) {
|
||||||
|
if (!dialog_id.is_valid()) {
|
||||||
|
LOG(ERROR) << "Resolve username \"" << username << "\" to invalid " << dialog_id;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto cleaned_username = clean_username(username);
|
||||||
|
if (cleaned_username.empty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto resolved_username = resolved_usernames_.get(cleaned_username);
|
||||||
|
if (resolved_username.dialog_id.is_valid()) {
|
||||||
|
LOG_IF(ERROR, resolved_username.dialog_id != dialog_id)
|
||||||
|
<< "Resolve username \"" << username << "\" to " << dialog_id << ", but have it in "
|
||||||
|
<< resolved_username.dialog_id;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
inaccessible_resolved_usernames_[cleaned_username] = dialog_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DialogManager::drop_username(const string &username) {
|
||||||
|
auto cleaned_username = clean_username(username);
|
||||||
|
if (cleaned_username.empty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
inaccessible_resolved_usernames_.erase(cleaned_username);
|
||||||
|
|
||||||
|
auto resolved_username = resolved_usernames_.get(cleaned_username);
|
||||||
|
if (resolved_username.dialog_id.is_valid()) {
|
||||||
|
auto dialog_id = resolved_username.dialog_id;
|
||||||
|
if (have_input_peer(dialog_id, AccessRights::Read)) {
|
||||||
|
CHECK(dialog_id.get_type() != DialogType::SecretChat);
|
||||||
|
reload_dialog_info_full(dialog_id, "drop_username");
|
||||||
|
}
|
||||||
|
|
||||||
|
resolved_usernames_.erase(cleaned_username);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace td
|
} // namespace td
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
|
|
||||||
#include "td/telegram/AccentColorId.h"
|
#include "td/telegram/AccentColorId.h"
|
||||||
#include "td/telegram/AccessRights.h"
|
#include "td/telegram/AccessRights.h"
|
||||||
|
#include "td/telegram/ChannelId.h"
|
||||||
#include "td/telegram/CustomEmojiId.h"
|
#include "td/telegram/CustomEmojiId.h"
|
||||||
#include "td/telegram/DialogId.h"
|
#include "td/telegram/DialogId.h"
|
||||||
#include "td/telegram/DialogParticipant.h"
|
#include "td/telegram/DialogParticipant.h"
|
||||||
@ -26,6 +27,7 @@
|
|||||||
#include "td/utils/FlatHashMap.h"
|
#include "td/utils/FlatHashMap.h"
|
||||||
#include "td/utils/Promise.h"
|
#include "td/utils/Promise.h"
|
||||||
#include "td/utils/Status.h"
|
#include "td/utils/Status.h"
|
||||||
|
#include "td/utils/WaitFreeHashMap.h"
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
@ -34,10 +36,16 @@ namespace td {
|
|||||||
|
|
||||||
class ReportReason;
|
class ReportReason;
|
||||||
class Td;
|
class Td;
|
||||||
|
class Usernames;
|
||||||
|
|
||||||
class DialogManager final : public Actor {
|
class DialogManager final : public Actor {
|
||||||
public:
|
public:
|
||||||
DialogManager(Td *td, ActorShared<> parent);
|
DialogManager(Td *td, ActorShared<> parent);
|
||||||
|
DialogManager(const DialogManager &) = delete;
|
||||||
|
DialogManager &operator=(const DialogManager &) = delete;
|
||||||
|
DialogManager(DialogManager &&) = delete;
|
||||||
|
DialogManager &operator=(DialogManager &&) = delete;
|
||||||
|
~DialogManager() final;
|
||||||
|
|
||||||
DialogId get_my_dialog_id() const;
|
DialogId get_my_dialog_id() const;
|
||||||
|
|
||||||
@ -157,9 +165,29 @@ class DialogManager final : public Actor {
|
|||||||
void upload_dialog_photo(DialogId dialog_id, FileId file_id, bool is_animation, double main_frame_timestamp,
|
void upload_dialog_photo(DialogId dialog_id, FileId file_id, bool is_animation, double main_frame_timestamp,
|
||||||
bool is_reupload, Promise<Unit> &&promise, vector<int> bad_parts = {});
|
bool is_reupload, Promise<Unit> &&promise, vector<int> bad_parts = {});
|
||||||
|
|
||||||
|
void on_dialog_usernames_updated(DialogId dialog_id, const Usernames &old_usernames, const Usernames &new_usernames);
|
||||||
|
|
||||||
|
void on_dialog_usernames_received(DialogId dialog_id, const Usernames &usernames, bool from_database);
|
||||||
|
|
||||||
|
void resolve_dialog(const string &username, ChannelId channel_id, Promise<DialogId> promise);
|
||||||
|
|
||||||
|
DialogId get_resolved_dialog_by_username(const string &username) const;
|
||||||
|
|
||||||
|
DialogId resolve_dialog_username(const string &username, Promise<Unit> &promise);
|
||||||
|
|
||||||
|
DialogId search_public_dialog(const string &username_to_search, bool force, Promise<Unit> &&promise);
|
||||||
|
|
||||||
|
void reload_voice_chat_on_search(const string &username);
|
||||||
|
|
||||||
|
void on_resolved_username(const string &username, DialogId dialog_id);
|
||||||
|
|
||||||
|
void drop_username(const string &username);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static constexpr size_t MAX_TITLE_LENGTH = 128; // server side limit for chat title
|
static constexpr size_t MAX_TITLE_LENGTH = 128; // server side limit for chat title
|
||||||
|
|
||||||
|
static constexpr int32 USERNAME_CACHE_EXPIRE_TIME = 86400;
|
||||||
|
|
||||||
void tear_down() final;
|
void tear_down() final;
|
||||||
|
|
||||||
void on_upload_dialog_photo(FileId file_id, telegram_api::object_ptr<telegram_api::InputFile> input_file);
|
void on_upload_dialog_photo(FileId file_id, telegram_api::object_ptr<telegram_api::InputFile> input_file);
|
||||||
@ -170,6 +198,10 @@ class DialogManager final : public Actor {
|
|||||||
telegram_api::object_ptr<telegram_api::InputChatPhoto> &&input_chat_photo,
|
telegram_api::object_ptr<telegram_api::InputChatPhoto> &&input_chat_photo,
|
||||||
Promise<Unit> &&promise);
|
Promise<Unit> &&promise);
|
||||||
|
|
||||||
|
void send_resolve_dialog_username_query(const string &username, Promise<Unit> &&promise);
|
||||||
|
|
||||||
|
void on_resolve_dialog(const string &username, ChannelId channel_id, Promise<DialogId> &&promise);
|
||||||
|
|
||||||
class UploadDialogPhotoCallback;
|
class UploadDialogPhotoCallback;
|
||||||
std::shared_ptr<UploadDialogPhotoCallback> upload_dialog_photo_callback_;
|
std::shared_ptr<UploadDialogPhotoCallback> upload_dialog_photo_callback_;
|
||||||
|
|
||||||
@ -191,6 +223,18 @@ class DialogManager final : public Actor {
|
|||||||
};
|
};
|
||||||
FlatHashMap<FileId, UploadedDialogPhotoInfo, FileIdHash> being_uploaded_dialog_photos_;
|
FlatHashMap<FileId, UploadedDialogPhotoInfo, FileIdHash> being_uploaded_dialog_photos_;
|
||||||
|
|
||||||
|
struct ResolvedUsername {
|
||||||
|
DialogId dialog_id;
|
||||||
|
double expires_at = 0.0;
|
||||||
|
|
||||||
|
ResolvedUsername() = default;
|
||||||
|
ResolvedUsername(DialogId dialog_id, double expires_at) : dialog_id(dialog_id), expires_at(expires_at) {
|
||||||
|
}
|
||||||
|
};
|
||||||
|
WaitFreeHashMap<string, ResolvedUsername> resolved_usernames_;
|
||||||
|
WaitFreeHashMap<string, DialogId> inaccessible_resolved_usernames_;
|
||||||
|
FlatHashSet<string> reload_voice_chat_on_search_usernames_;
|
||||||
|
|
||||||
Td *td_;
|
Td *td_;
|
||||||
ActorShared<> parent_;
|
ActorShared<> parent_;
|
||||||
};
|
};
|
||||||
|
@ -26,7 +26,6 @@
|
|||||||
#include "td/telegram/MessageContent.h"
|
#include "td/telegram/MessageContent.h"
|
||||||
#include "td/telegram/MessageContentType.h"
|
#include "td/telegram/MessageContentType.h"
|
||||||
#include "td/telegram/MessageEntity.h"
|
#include "td/telegram/MessageEntity.h"
|
||||||
#include "td/telegram/MessagesManager.h"
|
|
||||||
#include "td/telegram/misc.h"
|
#include "td/telegram/misc.h"
|
||||||
#include "td/telegram/net/DcId.h"
|
#include "td/telegram/net/DcId.h"
|
||||||
#include "td/telegram/Photo.h"
|
#include "td/telegram/Photo.h"
|
||||||
@ -2116,8 +2115,8 @@ bool InlineQueriesManager::load_recently_used_bots(Promise<Unit> &promise) {
|
|||||||
auto lock = resolve_recent_inline_bots_multipromise_.get_promise();
|
auto lock = resolve_recent_inline_bots_multipromise_.get_promise();
|
||||||
if (!G()->use_chat_info_database()) {
|
if (!G()->use_chat_info_database()) {
|
||||||
for (auto &bot_username : bot_usernames) {
|
for (auto &bot_username : bot_usernames) {
|
||||||
td_->messages_manager_->search_public_dialog(bot_username, false,
|
td_->dialog_manager_->search_public_dialog(bot_username, false,
|
||||||
resolve_recent_inline_bots_multipromise_.get_promise());
|
resolve_recent_inline_bots_multipromise_.get_promise());
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for (auto &bot_id : bot_ids) {
|
for (auto &bot_id : bot_ids) {
|
||||||
|
@ -331,7 +331,7 @@ class LinkManager::InternalLinkBotStart final : public InternalLink {
|
|||||||
autostart = true;
|
autostart = true;
|
||||||
} else {
|
} else {
|
||||||
const Td *td = G()->td().get_actor_unsafe();
|
const Td *td = G()->td().get_actor_unsafe();
|
||||||
auto dialog_id = td->messages_manager_->resolve_dialog_username(bot_username_);
|
auto dialog_id = td->dialog_manager_->get_resolved_dialog_by_username(bot_username_);
|
||||||
if (dialog_id.is_valid() && dialog_id.get_type() == DialogType::User &&
|
if (dialog_id.is_valid() && dialog_id.get_type() == DialogType::User &&
|
||||||
td->messages_manager_->get_dialog_has_last_message(dialog_id) &&
|
td->messages_manager_->get_dialog_has_last_message(dialog_id) &&
|
||||||
!td->messages_manager_->is_dialog_blocked(dialog_id)) {
|
!td->messages_manager_->is_dialog_blocked(dialog_id)) {
|
||||||
@ -1259,7 +1259,7 @@ unique_ptr<LinkManager::InternalLink> LinkManager::parse_tg_link_query(Slice que
|
|||||||
// resolve?domain=<username>&videochat
|
// resolve?domain=<username>&videochat
|
||||||
// resolve?domain=<username>&videochat=<invite_hash>
|
// resolve?domain=<username>&videochat=<invite_hash>
|
||||||
if (Scheduler::context() != nullptr) {
|
if (Scheduler::context() != nullptr) {
|
||||||
send_closure(G()->messages_manager(), &MessagesManager::reload_voice_chat_on_search, username);
|
send_closure(G()->dialog_manager(), &DialogManager::reload_voice_chat_on_search, username);
|
||||||
}
|
}
|
||||||
return td::make_unique<InternalLinkVoiceChat>(std::move(username), arg.second, arg.first == "livestream");
|
return td::make_unique<InternalLinkVoiceChat>(std::move(username), arg.second, arg.first == "livestream");
|
||||||
}
|
}
|
||||||
@ -1708,7 +1708,7 @@ unique_ptr<LinkManager::InternalLink> LinkManager::parse_t_me_link_query(Slice q
|
|||||||
// /<username>?videochat
|
// /<username>?videochat
|
||||||
// /<username>?videochat=<invite_hash>
|
// /<username>?videochat=<invite_hash>
|
||||||
if (Scheduler::context() != nullptr) {
|
if (Scheduler::context() != nullptr) {
|
||||||
send_closure(G()->messages_manager(), &MessagesManager::reload_voice_chat_on_search, username);
|
send_closure(G()->dialog_manager(), &DialogManager::reload_voice_chat_on_search, username);
|
||||||
}
|
}
|
||||||
return td::make_unique<InternalLinkVoiceChat>(std::move(username), arg.second, arg.first == "livestream");
|
return td::make_unique<InternalLinkVoiceChat>(std::move(username), arg.second, arg.first == "livestream");
|
||||||
}
|
}
|
||||||
|
@ -81,6 +81,7 @@
|
|||||||
#include "td/telegram/TopDialogManager.h"
|
#include "td/telegram/TopDialogManager.h"
|
||||||
#include "td/telegram/TranslationManager.h"
|
#include "td/telegram/TranslationManager.h"
|
||||||
#include "td/telegram/UpdatesManager.h"
|
#include "td/telegram/UpdatesManager.h"
|
||||||
|
#include "td/telegram/Usernames.h"
|
||||||
#include "td/telegram/Version.h"
|
#include "td/telegram/Version.h"
|
||||||
#include "td/telegram/WebPageId.h"
|
#include "td/telegram/WebPageId.h"
|
||||||
|
|
||||||
@ -3904,43 +3905,6 @@ class GetChannelDifferenceQuery final : public Td::ResultHandler {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class ResolveUsernameQuery final : public Td::ResultHandler {
|
|
||||||
Promise<Unit> promise_;
|
|
||||||
string username_;
|
|
||||||
|
|
||||||
public:
|
|
||||||
explicit ResolveUsernameQuery(Promise<Unit> &&promise) : promise_(std::move(promise)) {
|
|
||||||
}
|
|
||||||
|
|
||||||
void send(const string &username) {
|
|
||||||
username_ = username;
|
|
||||||
send_query(G()->net_query_creator().create(telegram_api::contacts_resolveUsername(username)));
|
|
||||||
}
|
|
||||||
|
|
||||||
void on_result(BufferSlice packet) final {
|
|
||||||
auto result_ptr = fetch_result<telegram_api::contacts_resolveUsername>(packet);
|
|
||||||
if (result_ptr.is_error()) {
|
|
||||||
return on_error(result_ptr.move_as_error());
|
|
||||||
}
|
|
||||||
|
|
||||||
auto ptr = result_ptr.move_as_ok();
|
|
||||||
LOG(DEBUG) << "Receive result for ResolveUsernameQuery: " << to_string(ptr);
|
|
||||||
td_->contacts_manager_->on_get_users(std::move(ptr->users_), "ResolveUsernameQuery");
|
|
||||||
td_->contacts_manager_->on_get_chats(std::move(ptr->chats_), "ResolveUsernameQuery");
|
|
||||||
|
|
||||||
td_->messages_manager_->on_resolved_username(username_, DialogId(ptr->peer_));
|
|
||||||
|
|
||||||
promise_.set_value(Unit());
|
|
||||||
}
|
|
||||||
|
|
||||||
void on_error(Status status) final {
|
|
||||||
if (status.message() == Slice("USERNAME_NOT_OCCUPIED")) {
|
|
||||||
td_->messages_manager_->drop_username(username_);
|
|
||||||
}
|
|
||||||
promise_.set_error(std::move(status));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
class MessagesManager::UploadMediaCallback final : public FileManager::UploadCallback {
|
class MessagesManager::UploadMediaCallback final : public FileManager::UploadCallback {
|
||||||
public:
|
public:
|
||||||
void on_upload_ok(FileId file_id, tl_object_ptr<telegram_api::InputFile> input_file) final {
|
void on_upload_ok(FileId file_id, tl_object_ptr<telegram_api::InputFile> input_file) final {
|
||||||
@ -5248,10 +5212,9 @@ MessagesManager::~MessagesManager() {
|
|||||||
message_embedding_codes_[1], message_to_replied_media_timestamp_messages_,
|
message_embedding_codes_[1], message_to_replied_media_timestamp_messages_,
|
||||||
story_to_replied_media_timestamp_messages_, notification_group_id_to_dialog_id_, pending_get_channel_differences_,
|
story_to_replied_media_timestamp_messages_, notification_group_id_to_dialog_id_, pending_get_channel_differences_,
|
||||||
active_get_channel_differences_, get_channel_difference_to_log_event_id_, channel_get_difference_retry_timeouts_,
|
active_get_channel_differences_, get_channel_difference_to_log_event_id_, channel_get_difference_retry_timeouts_,
|
||||||
is_channel_difference_finished_, expected_channel_pts_, expected_channel_max_message_id_, resolved_usernames_,
|
is_channel_difference_finished_, expected_channel_pts_, expected_channel_max_message_id_,
|
||||||
inaccessible_resolved_usernames_, dialog_bot_command_message_ids_, message_full_id_to_file_source_id_,
|
dialog_bot_command_message_ids_, message_full_id_to_file_source_id_, last_outgoing_forwarded_message_date_,
|
||||||
last_outgoing_forwarded_message_date_, dialog_viewed_messages_, previous_repaired_read_inbox_max_message_id_,
|
dialog_viewed_messages_, previous_repaired_read_inbox_max_message_id_, failed_to_load_dialogs_);
|
||||||
failed_to_load_dialogs_);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
MessagesManager::AddDialogData::AddDialogData(int32 dependent_dialog_count, unique_ptr<Message> &&last_message,
|
MessagesManager::AddDialogData::AddDialogData(int32 dependent_dialog_count, unique_ptr<Message> &&last_message,
|
||||||
@ -12669,7 +12632,7 @@ void MessagesManager::on_get_secret_message(SecretChatId secret_chat_id, UserId
|
|||||||
send_closure(actor_id, &MessagesManager::on_resolve_secret_chat_message_via_bot_username, via_bot_username,
|
send_closure(actor_id, &MessagesManager::on_resolve_secret_chat_message_via_bot_username, via_bot_username,
|
||||||
message_info_ptr, std::move(promise));
|
message_info_ptr, std::move(promise));
|
||||||
});
|
});
|
||||||
search_public_dialog(message->via_bot_name_, false, std::move(request_promise));
|
td_->dialog_manager_->search_public_dialog(message->via_bot_name_, false, std::move(request_promise));
|
||||||
}
|
}
|
||||||
|
|
||||||
message_info.content = get_secret_message_content(
|
message_info.content = get_secret_message_content(
|
||||||
@ -12684,7 +12647,7 @@ void MessagesManager::on_resolve_secret_chat_message_via_bot_username(const stri
|
|||||||
MessageInfo *message_info_ptr,
|
MessageInfo *message_info_ptr,
|
||||||
Promise<Unit> &&promise) {
|
Promise<Unit> &&promise) {
|
||||||
if (!G()->close_flag()) {
|
if (!G()->close_flag()) {
|
||||||
auto dialog_id = resolve_dialog_username(via_bot_username);
|
auto dialog_id = td_->dialog_manager_->get_resolved_dialog_by_username(via_bot_username);
|
||||||
if (dialog_id.is_valid() && dialog_id.get_type() == DialogType::User) {
|
if (dialog_id.is_valid() && dialog_id.get_type() == DialogType::User) {
|
||||||
auto user_id = dialog_id.get_user_id();
|
auto user_id = dialog_id.get_user_id();
|
||||||
auto r_bot_data = td_->contacts_manager_->get_bot_data(user_id);
|
auto r_bot_data = td_->contacts_manager_->get_bot_data(user_id);
|
||||||
@ -15839,18 +15802,12 @@ vector<DialogId> MessagesManager::search_public_dialogs(const string &query, Pro
|
|||||||
for (auto &short_username : get_valid_short_usernames()) {
|
for (auto &short_username : get_valid_short_usernames()) {
|
||||||
if (2 * username.size() > short_username.size() && begins_with(short_username, username)) {
|
if (2 * username.size() > short_username.size() && begins_with(short_username, username)) {
|
||||||
username = short_username.str();
|
username = short_username.str();
|
||||||
auto resolved_username = resolved_usernames_.get(username);
|
auto dialog_id = td_->dialog_manager_->resolve_dialog_username(username, promise);
|
||||||
if (!resolved_username.dialog_id.is_valid()) {
|
if (!dialog_id.is_valid()) {
|
||||||
send_resolve_dialog_username_query(username, std::move(promise));
|
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
if (resolved_username.expires_at < Time::now()) {
|
force_create_dialog(dialog_id, "search_public_dialogs");
|
||||||
send_resolve_dialog_username_query(username, Promise<Unit>());
|
|
||||||
}
|
|
||||||
|
|
||||||
auto dialog_id = resolved_username.dialog_id;
|
|
||||||
force_create_dialog(dialog_id, "public dialogs search");
|
|
||||||
|
|
||||||
auto d = get_dialog(dialog_id);
|
auto d = get_dialog(dialog_id);
|
||||||
if (d == nullptr || d->order != DEFAULT_ORDER ||
|
if (d == nullptr || d->order != DEFAULT_ORDER ||
|
||||||
@ -17155,7 +17112,7 @@ void MessagesManager::get_message_link_info(Slice url, Promise<MessageLinkInfo>
|
|||||||
send_closure(actor_id, &MessagesManager::on_get_message_link_dialog, std::move(info), result.ok(),
|
send_closure(actor_id, &MessagesManager::on_get_message_link_dialog, std::move(info), result.ok(),
|
||||||
std::move(promise));
|
std::move(promise));
|
||||||
});
|
});
|
||||||
resolve_dialog(info.username, info.channel_id, std::move(query_promise));
|
td_->dialog_manager_->resolve_dialog(info.username, info.channel_id, std::move(query_promise));
|
||||||
}
|
}
|
||||||
|
|
||||||
void MessagesManager::on_get_message_link_dialog(MessageLinkInfo &&info, DialogId dialog_id,
|
void MessagesManager::on_get_message_link_dialog(MessageLinkInfo &&info, DialogId dialog_id,
|
||||||
@ -17233,7 +17190,8 @@ td_api::object_ptr<td_api::messageLinkInfo> MessagesManager::get_message_link_in
|
|||||||
bool is_public = !info.username.empty();
|
bool is_public = !info.username.empty();
|
||||||
DialogId dialog_id = info.comment_dialog_id.is_valid()
|
DialogId dialog_id = info.comment_dialog_id.is_valid()
|
||||||
? info.comment_dialog_id
|
? info.comment_dialog_id
|
||||||
: (is_public ? resolve_dialog_username(info.username) : DialogId(info.channel_id));
|
: (is_public ? td_->dialog_manager_->get_resolved_dialog_by_username(info.username)
|
||||||
|
: DialogId(info.channel_id));
|
||||||
MessageId top_thread_message_id;
|
MessageId top_thread_message_id;
|
||||||
MessageId message_id = info.comment_dialog_id.is_valid() ? info.comment_message_id : info.message_id;
|
MessageId message_id = info.comment_dialog_id.is_valid() ? info.comment_message_id : info.message_id;
|
||||||
td_api::object_ptr<td_api::message> message;
|
td_api::object_ptr<td_api::message> message;
|
||||||
@ -30820,137 +30778,6 @@ void MessagesManager::on_dialog_linked_channel_updated(DialogId dialog_id, Chann
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void MessagesManager::send_resolve_dialog_username_query(const string &username, Promise<Unit> &&promise) {
|
|
||||||
td_->create_handler<ResolveUsernameQuery>(std::move(promise))->send(username);
|
|
||||||
}
|
|
||||||
|
|
||||||
void MessagesManager::resolve_dialog(const string &username, ChannelId channel_id, Promise<DialogId> promise) {
|
|
||||||
CHECK(username.empty() == channel_id.is_valid());
|
|
||||||
|
|
||||||
bool have_dialog = username.empty() ? td_->contacts_manager_->have_channel_force(channel_id, "resolve_dialog")
|
|
||||||
: resolve_dialog_username(username).is_valid();
|
|
||||||
if (!have_dialog) {
|
|
||||||
auto query_promise = PromiseCreator::lambda(
|
|
||||||
[actor_id = actor_id(this), username, channel_id, promise = std::move(promise)](Result<Unit> &&result) mutable {
|
|
||||||
if (result.is_error()) {
|
|
||||||
return promise.set_error(result.move_as_error());
|
|
||||||
}
|
|
||||||
send_closure(actor_id, &MessagesManager::on_resolve_dialog, username, channel_id, std::move(promise));
|
|
||||||
});
|
|
||||||
if (username.empty()) {
|
|
||||||
td_->contacts_manager_->reload_channel(channel_id, std::move(query_promise), "resolve_dialog");
|
|
||||||
} else {
|
|
||||||
send_resolve_dialog_username_query(username, std::move(query_promise));
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
return on_resolve_dialog(username, channel_id, std::move(promise));
|
|
||||||
}
|
|
||||||
|
|
||||||
void MessagesManager::on_resolve_dialog(const string &username, ChannelId channel_id, Promise<DialogId> &&promise) {
|
|
||||||
TRY_STATUS_PROMISE(promise, G()->close_status());
|
|
||||||
|
|
||||||
DialogId dialog_id;
|
|
||||||
if (username.empty()) {
|
|
||||||
if (!td_->contacts_manager_->have_channel(channel_id)) {
|
|
||||||
return promise.set_error(Status::Error(500, "Chat info not found"));
|
|
||||||
}
|
|
||||||
|
|
||||||
dialog_id = DialogId(channel_id);
|
|
||||||
force_create_dialog(dialog_id, "on_resolve_dialog");
|
|
||||||
} else {
|
|
||||||
dialog_id = resolve_dialog_username(username);
|
|
||||||
if (dialog_id.is_valid()) {
|
|
||||||
force_create_dialog(dialog_id, "on_resolve_dialog", true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Dialog *d = get_dialog_force(dialog_id, "on_get_message_link_dialog");
|
|
||||||
if (d == nullptr) {
|
|
||||||
return promise.set_error(Status::Error(500, "Chat not found"));
|
|
||||||
}
|
|
||||||
promise.set_value(std::move(dialog_id));
|
|
||||||
}
|
|
||||||
|
|
||||||
DialogId MessagesManager::resolve_dialog_username(const string &username) const {
|
|
||||||
auto cleaned_username = clean_username(username);
|
|
||||||
auto resolved_username = resolved_usernames_.get(cleaned_username);
|
|
||||||
if (resolved_username.dialog_id.is_valid()) {
|
|
||||||
return resolved_username.dialog_id;
|
|
||||||
}
|
|
||||||
|
|
||||||
return inaccessible_resolved_usernames_.get(cleaned_username);
|
|
||||||
}
|
|
||||||
|
|
||||||
DialogId MessagesManager::search_public_dialog(const string &username_to_search, bool force, Promise<Unit> &&promise) {
|
|
||||||
string username = clean_username(username_to_search);
|
|
||||||
if (username[0] == '@') {
|
|
||||||
username = username.substr(1);
|
|
||||||
}
|
|
||||||
if (username.empty()) {
|
|
||||||
promise.set_error(Status::Error(200, "Username is invalid"));
|
|
||||||
return DialogId();
|
|
||||||
}
|
|
||||||
|
|
||||||
DialogId dialog_id;
|
|
||||||
auto resolved_username = resolved_usernames_.get(username);
|
|
||||||
if (resolved_username.dialog_id.is_valid()) {
|
|
||||||
if (resolved_username.expires_at < Time::now()) {
|
|
||||||
send_resolve_dialog_username_query(username, Promise<Unit>());
|
|
||||||
}
|
|
||||||
dialog_id = resolved_username.dialog_id;
|
|
||||||
} else {
|
|
||||||
dialog_id = inaccessible_resolved_usernames_.get(username);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (dialog_id.is_valid()) {
|
|
||||||
if (td_->dialog_manager_->have_input_peer(dialog_id, AccessRights::Read)) {
|
|
||||||
if (!force && reload_voice_chat_on_search_usernames_.count(username)) {
|
|
||||||
reload_voice_chat_on_search_usernames_.erase(username);
|
|
||||||
if (dialog_id.get_type() == DialogType::Channel) {
|
|
||||||
td_->contacts_manager_->reload_channel_full(dialog_id.get_channel_id(), std::move(promise),
|
|
||||||
"search_public_dialog");
|
|
||||||
return DialogId();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (td_->auth_manager_->is_bot()) {
|
|
||||||
force_create_dialog(dialog_id, "search_public_dialog", true);
|
|
||||||
} else {
|
|
||||||
const Dialog *d = get_dialog_force(dialog_id, "search_public_dialog");
|
|
||||||
if (!is_dialog_inited(d)) {
|
|
||||||
send_get_dialog_query(dialog_id, std::move(promise), 0, "search_public_dialog");
|
|
||||||
return DialogId();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
promise.set_value(Unit());
|
|
||||||
return dialog_id;
|
|
||||||
} else {
|
|
||||||
// bot username maybe known despite there is no access_hash
|
|
||||||
if (force || dialog_id.get_type() != DialogType::User) {
|
|
||||||
force_create_dialog(dialog_id, "search_public_dialog", true);
|
|
||||||
promise.set_value(Unit());
|
|
||||||
return dialog_id;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
send_resolve_dialog_username_query(username, std::move(promise));
|
|
||||||
return DialogId();
|
|
||||||
}
|
|
||||||
|
|
||||||
void MessagesManager::reload_voice_chat_on_search(const string &username) {
|
|
||||||
if (!td_->auth_manager_->is_authorized()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto cleaned_username = clean_username(username);
|
|
||||||
if (!cleaned_username.empty()) {
|
|
||||||
reload_voice_chat_on_search_usernames_.insert(cleaned_username);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class MessagesManager::RegetDialogLogEvent {
|
class MessagesManager::RegetDialogLogEvent {
|
||||||
public:
|
public:
|
||||||
DialogId dialog_id_;
|
DialogId dialog_id_;
|
||||||
@ -31044,77 +30871,18 @@ void MessagesManager::on_get_dialog_query_finished(DialogId dialog_id, Status &&
|
|||||||
|
|
||||||
void MessagesManager::on_dialog_usernames_updated(DialogId dialog_id, const Usernames &old_usernames,
|
void MessagesManager::on_dialog_usernames_updated(DialogId dialog_id, const Usernames &old_usernames,
|
||||||
const Usernames &new_usernames) {
|
const Usernames &new_usernames) {
|
||||||
CHECK(dialog_id.is_valid());
|
if (td_->auth_manager_->is_bot()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
LOG(INFO) << "Update usernames in " << dialog_id << " from " << old_usernames << " to " << new_usernames;
|
LOG(INFO) << "Update usernames in " << dialog_id << " from " << old_usernames << " to " << new_usernames;
|
||||||
|
|
||||||
message_embedding_codes_[0].erase(dialog_id);
|
message_embedding_codes_[0].erase(dialog_id);
|
||||||
message_embedding_codes_[1].erase(dialog_id);
|
message_embedding_codes_[1].erase(dialog_id);
|
||||||
|
|
||||||
for (auto &username : old_usernames.get_active_usernames()) {
|
const auto *d = get_dialog(dialog_id);
|
||||||
auto cleaned_username = clean_username(username);
|
if (d != nullptr) {
|
||||||
resolved_usernames_.erase(cleaned_username);
|
update_dialogs_hints(d);
|
||||||
inaccessible_resolved_usernames_.erase(cleaned_username);
|
|
||||||
}
|
|
||||||
|
|
||||||
on_dialog_usernames_received(dialog_id, new_usernames, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
void MessagesManager::on_dialog_usernames_received(DialogId dialog_id, const Usernames &usernames, bool from_database) {
|
|
||||||
if (!td_->auth_manager_->is_bot()) {
|
|
||||||
const auto *d = get_dialog(dialog_id);
|
|
||||||
if (d != nullptr) {
|
|
||||||
update_dialogs_hints(d);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (auto &username : usernames.get_active_usernames()) {
|
|
||||||
auto cleaned_username = clean_username(username);
|
|
||||||
if (!cleaned_username.empty()) {
|
|
||||||
resolved_usernames_[cleaned_username] =
|
|
||||||
ResolvedUsername{dialog_id, Time::now() + (from_database ? 0 : USERNAME_CACHE_EXPIRE_TIME)};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void MessagesManager::on_resolved_username(const string &username, DialogId dialog_id) {
|
|
||||||
if (!dialog_id.is_valid()) {
|
|
||||||
LOG(ERROR) << "Resolve username \"" << username << "\" to invalid " << dialog_id;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto cleaned_username = clean_username(username);
|
|
||||||
if (cleaned_username.empty()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto resolved_username = resolved_usernames_.get(cleaned_username);
|
|
||||||
if (resolved_username.dialog_id.is_valid()) {
|
|
||||||
LOG_IF(ERROR, resolved_username.dialog_id != dialog_id)
|
|
||||||
<< "Resolve username \"" << username << "\" to " << dialog_id << ", but have it in "
|
|
||||||
<< resolved_username.dialog_id;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
inaccessible_resolved_usernames_[cleaned_username] = dialog_id;
|
|
||||||
}
|
|
||||||
|
|
||||||
void MessagesManager::drop_username(const string &username) {
|
|
||||||
auto cleaned_username = clean_username(username);
|
|
||||||
if (cleaned_username.empty()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
inaccessible_resolved_usernames_.erase(cleaned_username);
|
|
||||||
|
|
||||||
auto resolved_username = resolved_usernames_.get(cleaned_username);
|
|
||||||
if (resolved_username.dialog_id.is_valid()) {
|
|
||||||
auto dialog_id = resolved_username.dialog_id;
|
|
||||||
if (td_->dialog_manager_->have_input_peer(dialog_id, AccessRights::Read)) {
|
|
||||||
CHECK(dialog_id.get_type() != DialogType::SecretChat);
|
|
||||||
send_get_dialog_query(dialog_id, Auto(), 0, "drop_username");
|
|
||||||
}
|
|
||||||
|
|
||||||
resolved_usernames_.erase(cleaned_username);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -67,7 +67,6 @@
|
|||||||
#include "td/telegram/td_api.h"
|
#include "td/telegram/td_api.h"
|
||||||
#include "td/telegram/telegram_api.h"
|
#include "td/telegram/telegram_api.h"
|
||||||
#include "td/telegram/UserId.h"
|
#include "td/telegram/UserId.h"
|
||||||
#include "td/telegram/Usernames.h"
|
|
||||||
|
|
||||||
#include "td/actor/actor.h"
|
#include "td/actor/actor.h"
|
||||||
#include "td/actor/MultiPromise.h"
|
#include "td/actor/MultiPromise.h"
|
||||||
@ -111,6 +110,7 @@ struct InputMessageContent;
|
|||||||
class MessageContent;
|
class MessageContent;
|
||||||
struct MessageReactions;
|
struct MessageReactions;
|
||||||
class Td;
|
class Td;
|
||||||
|
class Usernames;
|
||||||
|
|
||||||
class MessagesManager final : public Actor {
|
class MessagesManager final : public Actor {
|
||||||
public:
|
public:
|
||||||
@ -383,14 +383,6 @@ class MessagesManager final : public Actor {
|
|||||||
|
|
||||||
std::pair<int32, vector<DialogId>> get_recently_opened_dialogs(int32 limit, Promise<Unit> &&promise);
|
std::pair<int32, vector<DialogId>> get_recently_opened_dialogs(int32 limit, Promise<Unit> &&promise);
|
||||||
|
|
||||||
void resolve_dialog(const string &username, ChannelId channel_id, Promise<DialogId> promise);
|
|
||||||
|
|
||||||
DialogId resolve_dialog_username(const string &username) const;
|
|
||||||
|
|
||||||
DialogId search_public_dialog(const string &username_to_search, bool force, Promise<Unit> &&promise);
|
|
||||||
|
|
||||||
void reload_voice_chat_on_search(const string &username);
|
|
||||||
|
|
||||||
void get_dialog_send_message_as_dialog_ids(DialogId dialog_id,
|
void get_dialog_send_message_as_dialog_ids(DialogId dialog_id,
|
||||||
Promise<td_api::object_ptr<td_api::chatMessageSenders>> &&promise,
|
Promise<td_api::object_ptr<td_api::chatMessageSenders>> &&promise,
|
||||||
bool is_recursive = false);
|
bool is_recursive = false);
|
||||||
@ -809,7 +801,6 @@ class MessagesManager final : public Actor {
|
|||||||
void on_dialog_title_updated(DialogId dialog_id);
|
void on_dialog_title_updated(DialogId dialog_id);
|
||||||
void on_dialog_emoji_status_updated(DialogId dialog_id);
|
void on_dialog_emoji_status_updated(DialogId dialog_id);
|
||||||
void on_dialog_usernames_updated(DialogId dialog_id, const Usernames &old_usernames, const Usernames &new_usernames);
|
void on_dialog_usernames_updated(DialogId dialog_id, const Usernames &old_usernames, const Usernames &new_usernames);
|
||||||
void on_dialog_usernames_received(DialogId dialog_id, const Usernames &usernames, bool from_database);
|
|
||||||
void on_dialog_default_permissions_updated(DialogId dialog_id);
|
void on_dialog_default_permissions_updated(DialogId dialog_id);
|
||||||
void on_dialog_has_protected_content_updated(DialogId dialog_id);
|
void on_dialog_has_protected_content_updated(DialogId dialog_id);
|
||||||
|
|
||||||
@ -821,9 +812,6 @@ class MessagesManager final : public Actor {
|
|||||||
|
|
||||||
void drop_dialog_pending_join_requests(DialogId dialog_id);
|
void drop_dialog_pending_join_requests(DialogId dialog_id);
|
||||||
|
|
||||||
void on_resolved_username(const string &username, DialogId dialog_id);
|
|
||||||
void drop_username(const string &username);
|
|
||||||
|
|
||||||
void on_update_notification_scope_is_muted(NotificationSettingsScope scope, bool is_muted);
|
void on_update_notification_scope_is_muted(NotificationSettingsScope scope, bool is_muted);
|
||||||
|
|
||||||
void on_update_dialog_notify_settings(DialogId dialog_id,
|
void on_update_dialog_notify_settings(DialogId dialog_id,
|
||||||
@ -1628,7 +1616,6 @@ class MessagesManager final : public Actor {
|
|||||||
static constexpr int32 LIVE_LOCATION_VIEW_PERIOD = 60; // seconds, server-side limit
|
static constexpr int32 LIVE_LOCATION_VIEW_PERIOD = 60; // seconds, server-side limit
|
||||||
static constexpr int32 UPDATE_VIEWED_MESSAGES_PERIOD = 15; // seconds
|
static constexpr int32 UPDATE_VIEWED_MESSAGES_PERIOD = 15; // seconds
|
||||||
|
|
||||||
static constexpr int32 USERNAME_CACHE_EXPIRE_TIME = 86400;
|
|
||||||
static constexpr int32 AUTH_NOTIFICATION_ID_CACHE_TIME = 7 * 86400;
|
static constexpr int32 AUTH_NOTIFICATION_ID_CACHE_TIME = 7 * 86400;
|
||||||
static constexpr size_t MAX_SAVED_AUTH_NOTIFICATION_IDS = 100;
|
static constexpr size_t MAX_SAVED_AUTH_NOTIFICATION_IDS = 100;
|
||||||
|
|
||||||
@ -1895,10 +1882,6 @@ class MessagesManager final : public Actor {
|
|||||||
|
|
||||||
bool is_message_unload_enabled() const;
|
bool is_message_unload_enabled() const;
|
||||||
|
|
||||||
void send_resolve_dialog_username_query(const string &username, Promise<Unit> &&promise);
|
|
||||||
|
|
||||||
void on_resolve_dialog(const string &username, ChannelId channel_id, Promise<DialogId> &&promise);
|
|
||||||
|
|
||||||
int64 generate_new_media_album_id();
|
int64 generate_new_media_album_id();
|
||||||
|
|
||||||
static bool can_forward_message(DialogId from_dialog_id, const Message *m);
|
static bool can_forward_message(DialogId from_dialog_id, const Message *m);
|
||||||
@ -3321,19 +3304,6 @@ class MessagesManager final : public Actor {
|
|||||||
|
|
||||||
FlatHashMap<DialogId, vector<Promise<Unit>>, DialogIdHash> load_scheduled_messages_from_database_queries_;
|
FlatHashMap<DialogId, vector<Promise<Unit>>, DialogIdHash> load_scheduled_messages_from_database_queries_;
|
||||||
|
|
||||||
struct ResolvedUsername {
|
|
||||||
DialogId dialog_id;
|
|
||||||
double expires_at = 0.0;
|
|
||||||
|
|
||||||
ResolvedUsername() = default;
|
|
||||||
ResolvedUsername(DialogId dialog_id, double expires_at) : dialog_id(dialog_id), expires_at(expires_at) {
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
WaitFreeHashMap<string, ResolvedUsername> resolved_usernames_;
|
|
||||||
WaitFreeHashMap<string, DialogId> inaccessible_resolved_usernames_;
|
|
||||||
FlatHashSet<string> reload_voice_chat_on_search_usernames_;
|
|
||||||
|
|
||||||
struct GetDialogsTask {
|
struct GetDialogsTask {
|
||||||
DialogListId dialog_list_id;
|
DialogListId dialog_list_id;
|
||||||
int32 limit;
|
int32 limit;
|
||||||
|
@ -99,7 +99,7 @@ void RecentDialogList::load_dialogs(Promise<Unit> &&promise) {
|
|||||||
vector<DialogId> dialog_ids;
|
vector<DialogId> dialog_ids;
|
||||||
for (auto &found_dialog : found_dialogs) {
|
for (auto &found_dialog : found_dialogs) {
|
||||||
if (found_dialog[0] == '@') {
|
if (found_dialog[0] == '@') {
|
||||||
td_->messages_manager_->search_public_dialog(found_dialog, false, mpas.get_promise());
|
td_->dialog_manager_->search_public_dialog(found_dialog, false, mpas.get_promise());
|
||||||
} else {
|
} else {
|
||||||
dialog_ids.push_back(DialogId(to_integer<int64>(found_dialog)));
|
dialog_ids.push_back(DialogId(to_integer<int64>(found_dialog)));
|
||||||
}
|
}
|
||||||
@ -137,7 +137,7 @@ void RecentDialogList::on_load_dialogs(vector<string> &&found_dialogs) {
|
|||||||
for (auto it = found_dialogs.rbegin(); it != found_dialogs.rend(); ++it) {
|
for (auto it = found_dialogs.rbegin(); it != found_dialogs.rend(); ++it) {
|
||||||
DialogId dialog_id;
|
DialogId dialog_id;
|
||||||
if ((*it)[0] == '@') {
|
if ((*it)[0] == '@') {
|
||||||
dialog_id = td_->messages_manager_->resolve_dialog_username(it->substr(1));
|
dialog_id = td_->dialog_manager_->get_resolved_dialog_by_username(it->substr(1));
|
||||||
} else {
|
} else {
|
||||||
dialog_id = DialogId(to_integer<int64>(*it));
|
dialog_id = DialogId(to_integer<int64>(*it));
|
||||||
}
|
}
|
||||||
|
@ -791,7 +791,7 @@ class SearchPublicChatRequest final : public RequestActor<> {
|
|||||||
DialogId dialog_id_;
|
DialogId dialog_id_;
|
||||||
|
|
||||||
void do_run(Promise<Unit> &&promise) final {
|
void do_run(Promise<Unit> &&promise) final {
|
||||||
dialog_id_ = td_->messages_manager_->search_public_dialog(username_, get_tries() < 3, std::move(promise));
|
dialog_id_ = td_->dialog_manager_->search_public_dialog(username_, get_tries() < 3, std::move(promise));
|
||||||
}
|
}
|
||||||
|
|
||||||
void do_send_result() final {
|
void do_send_result() final {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user