Merge remote-tracking branch 'td/master'
This commit is contained in:
commit
9ca532c6a6
@ -416,6 +416,7 @@ set(TDLIB_SOURCE
|
|||||||
td/telegram/TdDb.cpp
|
td/telegram/TdDb.cpp
|
||||||
td/telegram/TermsOfService.cpp
|
td/telegram/TermsOfService.cpp
|
||||||
td/telegram/ThemeManager.cpp
|
td/telegram/ThemeManager.cpp
|
||||||
|
td/telegram/TopDialogCategory.cpp
|
||||||
td/telegram/TopDialogManager.cpp
|
td/telegram/TopDialogManager.cpp
|
||||||
td/telegram/UpdatesManager.cpp
|
td/telegram/UpdatesManager.cpp
|
||||||
td/telegram/Venue.cpp
|
td/telegram/Venue.cpp
|
||||||
|
@ -173,7 +173,7 @@ See [project.scarlet](https://github.com/aaugmentum/project.scarlet), [tdlib](ht
|
|||||||
|
|
||||||
TDLib can be used from the Rust programming language through the [JSON](https://github.com/tdlib/td#using-json) interface.
|
TDLib can be used from the Rust programming language through the [JSON](https://github.com/tdlib/td#using-json) interface.
|
||||||
|
|
||||||
See [rust-tdlib](https://github.com/aCLr/rust-tdlib) or [tdlib-rs](https://github.com/agnipau/tdlib-rs), which provide convenient TDLib clients with automatically generated and fully-documented classes for all TDLib API methods and objects.
|
See [rust-tdlib](https://github.com/aCLr/rust-tdlib), [tdgrand](https://github.com/melix99/tdgrand), or [tdlib-rs](https://github.com/agnipau/tdlib-rs), which provide convenient TDLib clients with automatically generated and fully-documented classes for all TDLib API methods and objects.
|
||||||
|
|
||||||
See [rtdlib](https://github.com/fewensa/rtdlib), [tdlib-rs](https://github.com/d653/tdlib-rs), [tdlib-futures](https://github.com/yuri91/tdlib-futures),
|
See [rtdlib](https://github.com/fewensa/rtdlib), [tdlib-rs](https://github.com/d653/tdlib-rs), [tdlib-futures](https://github.com/yuri91/tdlib-futures),
|
||||||
[tdlib-sys](https://github.com/nuxeh/tdlib-sys), or
|
[tdlib-sys](https://github.com/nuxeh/tdlib-sys), or
|
||||||
|
@ -4690,7 +4690,7 @@ joinChat chat_id:int53 = Ok;
|
|||||||
leaveChat chat_id:int53 = Ok;
|
leaveChat chat_id:int53 = Ok;
|
||||||
|
|
||||||
//@description Adds a new member to a chat. Members can't be added to private or secret chats
|
//@description Adds a new member to a chat. Members can't be added to private or secret chats
|
||||||
//@chat_id Chat identifier @user_id Identifier of the user @forward_limit The number of earlier messages from the chat to be forwarded to the new member; up to 100. Ignored for supergroups and channels
|
//@chat_id Chat identifier @user_id Identifier of the user @forward_limit The number of earlier messages from the chat to be forwarded to the new member; up to 100. Ignored for supergroups and channels, or if the added user is a bot
|
||||||
addChatMember chat_id:int53 user_id:int53 forward_limit:int32 = Ok;
|
addChatMember chat_id:int53 user_id:int53 forward_limit:int32 = Ok;
|
||||||
|
|
||||||
//@description Adds multiple new members to a chat. Currently this method is only available for supergroups and channels. This method can't be used to join a chat. Members can't be added to a channel if it has more than 200 members
|
//@description Adds multiple new members to a chat. Currently this method is only available for supergroups and channels. This method can't be used to join a chat. Members can't be added to a channel if it has more than 200 members
|
||||||
|
@ -784,7 +784,7 @@ void AuthManager::on_get_authorization(tl_object_ptr<telegram_api::auth_Authoriz
|
|||||||
td->notification_manager_->init();
|
td->notification_manager_->init();
|
||||||
td->stickers_manager_->init();
|
td->stickers_manager_->init();
|
||||||
td->theme_manager_->init();
|
td->theme_manager_->init();
|
||||||
send_closure(td->top_dialog_manager_, &TopDialogManager::do_start_up);
|
td->top_dialog_manager_->init();
|
||||||
td->updates_manager_->get_difference("on_get_authorization");
|
td->updates_manager_->get_difference("on_get_authorization");
|
||||||
td->on_online_updated(false, true);
|
td->on_online_updated(false, true);
|
||||||
if (!is_bot()) {
|
if (!is_bot()) {
|
||||||
|
@ -25,7 +25,7 @@ class Td;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* This is a low-level Actor interface for interaction with TDLib. The interface is a lot more flexible than
|
* This is a low-level Actor interface for interaction with TDLib. The interface is a lot more flexible than
|
||||||
* the Client interface, however, for most usages the Client interface should be sufficient.
|
* the ClientManager interface, however, for most usages the ClientManager interface should be sufficient.
|
||||||
*/
|
*/
|
||||||
class ClientActor final : public Actor {
|
class ClientActor final : public Actor {
|
||||||
public:
|
public:
|
||||||
|
@ -18,7 +18,7 @@
|
|||||||
|
|
||||||
namespace td {
|
namespace td {
|
||||||
|
|
||||||
// TODO can be made private in TDLib 2.0
|
// TODO can be removed in TDLib 2.0
|
||||||
class ClientJson final {
|
class ClientJson final {
|
||||||
public:
|
public:
|
||||||
void send(Slice request);
|
void send(Slice request);
|
||||||
|
@ -1743,7 +1743,7 @@ bool InlineQueriesManager::load_recently_used_bots(Promise<Unit> &promise) {
|
|||||||
auto bot_ids = full_split(saved_bot_ids, ',');
|
auto bot_ids = full_split(saved_bot_ids, ',');
|
||||||
string saved_bots = G()->td_db()->get_binlog_pmc()->get("recently_used_inline_bot_usernames");
|
string saved_bots = G()->td_db()->get_binlog_pmc()->get("recently_used_inline_bot_usernames");
|
||||||
auto bot_usernames = full_split(saved_bots, ',');
|
auto bot_usernames = full_split(saved_bots, ',');
|
||||||
if (bot_ids.empty() && bot_usernames.empty()) {
|
if (bot_ids.empty()) {
|
||||||
recently_used_bots_loaded_ = 2;
|
recently_used_bots_loaded_ = 2;
|
||||||
if (!recently_used_bot_user_ids_.empty()) {
|
if (!recently_used_bot_user_ids_.empty()) {
|
||||||
save_recently_used_bots();
|
save_recently_used_bots();
|
||||||
@ -1757,15 +1757,6 @@ bool InlineQueriesManager::load_recently_used_bots(Promise<Unit> &promise) {
|
|||||||
auto newly_used_bots = std::move(recently_used_bot_user_ids_);
|
auto newly_used_bots = std::move(recently_used_bot_user_ids_);
|
||||||
recently_used_bot_user_ids_.clear();
|
recently_used_bot_user_ids_.clear();
|
||||||
|
|
||||||
if (bot_ids.empty()) {
|
|
||||||
// legacy, can be removed in the future
|
|
||||||
for (auto it = bot_usernames.rbegin(); it != bot_usernames.rend(); ++it) {
|
|
||||||
auto dialog_id = td_->messages_manager_->resolve_dialog_username(*it);
|
|
||||||
if (dialog_id.get_type() == DialogType::User) {
|
|
||||||
update_bot_usage(dialog_id.get_user_id());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
for (auto it = bot_ids.rbegin(); it != bot_ids.rend(); ++it) {
|
for (auto it = bot_ids.rbegin(); it != bot_ids.rend(); ++it) {
|
||||||
UserId user_id(to_integer<int64>(*it));
|
UserId user_id(to_integer<int64>(*it));
|
||||||
if (td_->contacts_manager_->have_user(user_id)) {
|
if (td_->contacts_manager_->have_user(user_id)) {
|
||||||
@ -1774,12 +1765,11 @@ bool InlineQueriesManager::load_recently_used_bots(Promise<Unit> &promise) {
|
|||||||
LOG(ERROR) << "Can't find " << user_id;
|
LOG(ERROR) << "Can't find " << user_id;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
for (auto it = newly_used_bots.rbegin(); it != newly_used_bots.rend(); ++it) {
|
for (auto it = newly_used_bots.rbegin(); it != newly_used_bots.rend(); ++it) {
|
||||||
update_bot_usage(*it);
|
update_bot_usage(*it);
|
||||||
}
|
}
|
||||||
recently_used_bots_loaded_ = 2;
|
recently_used_bots_loaded_ = 2;
|
||||||
if (!newly_used_bots.empty() || (bot_ids.empty() && !bot_usernames.empty())) {
|
if (!newly_used_bots.empty()) {
|
||||||
save_recently_used_bots();
|
save_recently_used_bots();
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
@ -1788,7 +1778,7 @@ bool InlineQueriesManager::load_recently_used_bots(Promise<Unit> &promise) {
|
|||||||
resolve_recent_inline_bots_multipromise_.add_promise(std::move(promise));
|
resolve_recent_inline_bots_multipromise_.add_promise(std::move(promise));
|
||||||
if (recently_used_bots_loaded_ == 0) {
|
if (recently_used_bots_loaded_ == 0) {
|
||||||
resolve_recent_inline_bots_multipromise_.set_ignore_errors(true);
|
resolve_recent_inline_bots_multipromise_.set_ignore_errors(true);
|
||||||
if (bot_ids.empty() || !G()->parameters().use_chat_info_db) {
|
if (!G()->parameters().use_chat_info_db) {
|
||||||
for (auto &bot_username : bot_usernames) {
|
for (auto &bot_username : bot_usernames) {
|
||||||
td_->messages_manager_->search_public_dialog(bot_username, false,
|
td_->messages_manager_->search_public_dialog(bot_username, false,
|
||||||
resolve_recent_inline_bots_multipromise_.get_promise());
|
resolve_recent_inline_bots_multipromise_.get_promise());
|
||||||
|
@ -15434,7 +15434,7 @@ bool MessagesManager::have_dialog(DialogId dialog_id) const {
|
|||||||
return dialogs_.count(dialog_id) > 0;
|
return dialogs_.count(dialog_id) > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MessagesManager::load_dialogs(vector<DialogId> dialog_ids, Promise<Unit> &&promise) {
|
void MessagesManager::load_dialogs(vector<DialogId> dialog_ids, Promise<vector<DialogId>> &&promise) {
|
||||||
LOG(INFO) << "Load chats " << format::as_array(dialog_ids);
|
LOG(INFO) << "Load chats " << format::as_array(dialog_ids);
|
||||||
|
|
||||||
Dependencies dependencies;
|
Dependencies dependencies;
|
||||||
@ -15445,13 +15445,14 @@ void MessagesManager::load_dialogs(vector<DialogId> dialog_ids, Promise<Unit> &&
|
|||||||
}
|
}
|
||||||
resolve_dependencies_force(td_, dependencies, "load_dialogs");
|
resolve_dependencies_force(td_, dependencies, "load_dialogs");
|
||||||
|
|
||||||
|
td::remove_if(dialog_ids, [this](DialogId dialog_id) { return !have_dialog_info(dialog_id); });
|
||||||
|
|
||||||
for (auto dialog_id : dialog_ids) {
|
for (auto dialog_id : dialog_ids) {
|
||||||
if (dialog_id.is_valid()) {
|
|
||||||
force_create_dialog(dialog_id, "load_dialogs");
|
force_create_dialog(dialog_id, "load_dialogs");
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
promise.set_value(Unit());
|
LOG(INFO) << "Loaded chats " << format::as_array(dialog_ids);
|
||||||
|
promise.set_value(std::move(dialog_ids));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MessagesManager::load_dialog(DialogId dialog_id, int left_tries, Promise<Unit> &&promise) {
|
bool MessagesManager::load_dialog(DialogId dialog_id, int left_tries, Promise<Unit> &&promise) {
|
||||||
|
@ -516,7 +516,7 @@ class MessagesManager final : public Actor {
|
|||||||
|
|
||||||
bool load_dialog(DialogId dialog_id, int left_tries, Promise<Unit> &&promise);
|
bool load_dialog(DialogId dialog_id, int left_tries, Promise<Unit> &&promise);
|
||||||
|
|
||||||
void load_dialogs(vector<DialogId> dialog_ids, Promise<Unit> &&promise);
|
void load_dialogs(vector<DialogId> dialog_ids, Promise<vector<DialogId>> &&promise);
|
||||||
|
|
||||||
void load_dialog_filter(DialogFilterId dialog_id, bool force, Promise<Unit> &&promise);
|
void load_dialog_filter(DialogFilterId dialog_id, bool force, Promise<Unit> &&promise);
|
||||||
|
|
||||||
|
@ -46,12 +46,14 @@ void RecentDialogList::save_dialogs() const {
|
|||||||
SliceBuilder sb;
|
SliceBuilder sb;
|
||||||
for (auto &dialog_id : dialog_ids_) {
|
for (auto &dialog_id : dialog_ids_) {
|
||||||
sb << ',';
|
sb << ',';
|
||||||
if (!G()->parameters().use_message_db) {
|
if (!G()->parameters().use_chat_info_db) {
|
||||||
// if there is no dialog database, prefer to save dialogs by username
|
// if there is no dialog info database, prefer to save dialogs by username
|
||||||
string username;
|
string username;
|
||||||
switch (dialog_id.get_type()) {
|
switch (dialog_id.get_type()) {
|
||||||
case DialogType::User:
|
case DialogType::User:
|
||||||
|
if (!td_->contacts_manager_->is_user_contact(dialog_id.get_user_id())) {
|
||||||
username = td_->contacts_manager_->get_user_username(dialog_id.get_user_id());
|
username = td_->contacts_manager_->get_user_username(dialog_id.get_user_id());
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case DialogType::Chat:
|
case DialogType::Chat:
|
||||||
break;
|
break;
|
||||||
@ -104,10 +106,7 @@ void RecentDialogList::load_dialogs(Promise<Unit> &&promise) {
|
|||||||
dialog_ids.push_back(DialogId(to_integer<int64>(found_dialog)));
|
dialog_ids.push_back(DialogId(to_integer<int64>(found_dialog)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!dialog_ids.empty()) {
|
if (!dialog_ids.empty() && !G()->parameters().use_chat_info_db) {
|
||||||
if (G()->parameters().use_message_db) {
|
|
||||||
td_->messages_manager_->load_dialogs(std::move(dialog_ids), mpas.get_promise());
|
|
||||||
} else {
|
|
||||||
td_->messages_manager_->get_dialogs_from_list(
|
td_->messages_manager_->get_dialogs_from_list(
|
||||||
DialogListId(FolderId::main()), 102,
|
DialogListId(FolderId::main()), 102,
|
||||||
PromiseCreator::lambda([promise = mpas.get_promise()](td_api::object_ptr<td_api::chats> &&chats) mutable {
|
PromiseCreator::lambda([promise = mpas.get_promise()](td_api::object_ptr<td_api::chats> &&chats) mutable {
|
||||||
@ -115,7 +114,6 @@ void RecentDialogList::load_dialogs(Promise<Unit> &&promise) {
|
|||||||
}));
|
}));
|
||||||
td_->contacts_manager_->search_contacts("", 1, mpas.get_promise());
|
td_->contacts_manager_->search_contacts("", 1, mpas.get_promise());
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
lock.set_value(Unit());
|
lock.set_value(Unit());
|
||||||
}
|
}
|
||||||
@ -135,6 +133,7 @@ void RecentDialogList::on_load_dialogs(vector<string> &&found_dialogs) {
|
|||||||
dialog_id = DialogId(to_integer<int64>(*it));
|
dialog_id = DialogId(to_integer<int64>(*it));
|
||||||
}
|
}
|
||||||
if (dialog_id.is_valid() && removed_dialog_ids_.count(dialog_id) == 0 &&
|
if (dialog_id.is_valid() && removed_dialog_ids_.count(dialog_id) == 0 &&
|
||||||
|
td_->messages_manager_->have_dialog_info(dialog_id) &&
|
||||||
td_->messages_manager_->have_input_peer(dialog_id, AccessRights::Read)) {
|
td_->messages_manager_->have_input_peer(dialog_id, AccessRights::Read)) {
|
||||||
td_->messages_manager_->force_create_dialog(dialog_id, "recent dialog");
|
td_->messages_manager_->force_create_dialog(dialog_id, "recent dialog");
|
||||||
do_add_dialog(dialog_id);
|
do_add_dialog(dialog_id);
|
||||||
|
@ -4583,7 +4583,7 @@ void StickersManager::invalidate_old_featured_sticker_sets() {
|
|||||||
auto promises = std::move(load_old_featured_sticker_sets_queries_);
|
auto promises = std::move(load_old_featured_sticker_sets_queries_);
|
||||||
load_old_featured_sticker_sets_queries_.clear();
|
load_old_featured_sticker_sets_queries_.clear();
|
||||||
for (auto &promise : promises) {
|
for (auto &promise : promises) {
|
||||||
promise.set_error(Status::Error(400, "Trending sticker sets was updated"));
|
promise.set_error(Status::Error(400, "Trending sticker sets were updated"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -166,7 +166,7 @@ void StorageManager::on_all_files(FileGcParameters gc_parameters, Result<FileSta
|
|||||||
|
|
||||||
create_gc_worker();
|
create_gc_worker();
|
||||||
|
|
||||||
send_closure(gc_worker_, &FileGcWorker::run_gc, std::move(gc_parameters), std::move(r_file_stats.ok_ref().all_files),
|
send_closure(gc_worker_, &FileGcWorker::run_gc, std::move(gc_parameters), r_file_stats.ok_ref().get_all_files(),
|
||||||
PromiseCreator::lambda([actor_id = actor_id(this), dialog_limit](Result<FileGcResult> r_file_gc_result) {
|
PromiseCreator::lambda([actor_id = actor_id(this), dialog_limit](Result<FileGcResult> r_file_gc_result) {
|
||||||
send_closure(actor_id, &StorageManager::on_gc_finished, dialog_limit, std::move(r_file_gc_result));
|
send_closure(actor_id, &StorageManager::on_gc_finished, dialog_limit, std::move(r_file_gc_result));
|
||||||
}));
|
}));
|
||||||
@ -264,7 +264,9 @@ void StorageManager::send_stats(FileStats &&stats, int32 dialog_limit, std::vect
|
|||||||
stats.apply_dialog_limit(dialog_limit);
|
stats.apply_dialog_limit(dialog_limit);
|
||||||
auto dialog_ids = stats.get_dialog_ids();
|
auto dialog_ids = stats.get_dialog_ids();
|
||||||
|
|
||||||
auto promise = PromiseCreator::lambda([promises = std::move(promises), stats = std::move(stats)](Unit) mutable {
|
auto promise = PromiseCreator::lambda(
|
||||||
|
[promises = std::move(promises), stats = std::move(stats)](vector<DialogId> dialog_ids) mutable {
|
||||||
|
stats.apply_dialog_ids(dialog_ids);
|
||||||
for (auto &promise : promises) {
|
for (auto &promise : promises) {
|
||||||
promise.set_value(FileStats(stats));
|
promise.set_value(FileStats(stats));
|
||||||
}
|
}
|
||||||
|
@ -40,6 +40,7 @@
|
|||||||
#include "td/telegram/files/FileId.h"
|
#include "td/telegram/files/FileId.h"
|
||||||
#include "td/telegram/files/FileManager.h"
|
#include "td/telegram/files/FileManager.h"
|
||||||
#include "td/telegram/files/FileSourceId.h"
|
#include "td/telegram/files/FileSourceId.h"
|
||||||
|
#include "td/telegram/files/FileStats.h"
|
||||||
#include "td/telegram/files/FileType.h"
|
#include "td/telegram/files/FileType.h"
|
||||||
#include "td/telegram/FolderId.h"
|
#include "td/telegram/FolderId.h"
|
||||||
#include "td/telegram/FullMessageId.h"
|
#include "td/telegram/FullMessageId.h"
|
||||||
@ -3437,12 +3438,12 @@ void Td::on_config_option_updated(const string &name) {
|
|||||||
} else if (name == "use_storage_optimizer") {
|
} else if (name == "use_storage_optimizer") {
|
||||||
send_closure(storage_manager_, &StorageManager::update_use_storage_optimizer);
|
send_closure(storage_manager_, &StorageManager::update_use_storage_optimizer);
|
||||||
} else if (name == "rating_e_decay") {
|
} else if (name == "rating_e_decay") {
|
||||||
return send_closure(top_dialog_manager_, &TopDialogManager::update_rating_e_decay);
|
return send_closure(top_dialog_manager_actor_, &TopDialogManager::update_rating_e_decay);
|
||||||
} else if (name == "disable_contact_registered_notifications") {
|
} else if (name == "disable_contact_registered_notifications") {
|
||||||
send_closure(notification_manager_actor_,
|
send_closure(notification_manager_actor_,
|
||||||
&NotificationManager::on_disable_contact_registered_notifications_changed);
|
&NotificationManager::on_disable_contact_registered_notifications_changed);
|
||||||
} else if (name == "disable_top_chats") {
|
} else if (name == "disable_top_chats") {
|
||||||
send_closure(top_dialog_manager_, &TopDialogManager::update_is_enabled,
|
send_closure(top_dialog_manager_actor_, &TopDialogManager::update_is_enabled,
|
||||||
!G()->shared_config().get_option_boolean(name));
|
!G()->shared_config().get_option_boolean(name));
|
||||||
} else if (name == "connection_parameters") {
|
} else if (name == "connection_parameters") {
|
||||||
if (G()->mtproto_header().set_parameters(G()->shared_config().get_option_string(name))) {
|
if (G()->mtproto_header().set_parameters(G()->shared_config().get_option_string(name))) {
|
||||||
@ -3616,6 +3617,8 @@ void Td::dec_actor_refcnt() {
|
|||||||
LOG(DEBUG) << "MemoryManager was cleared" << timer;
|
LOG(DEBUG) << "MemoryManager was cleared" << timer;
|
||||||
theme_manager_.reset();
|
theme_manager_.reset();
|
||||||
LOG(DEBUG) << "ThemeManager was cleared" << timer;
|
LOG(DEBUG) << "ThemeManager was cleared" << timer;
|
||||||
|
top_dialog_manager_.reset();
|
||||||
|
LOG(DEBUG) << "TopDialogManager was cleared" << timer;
|
||||||
updates_manager_.reset();
|
updates_manager_.reset();
|
||||||
LOG(DEBUG) << "UpdatesManager was cleared" << timer;
|
LOG(DEBUG) << "UpdatesManager was cleared" << timer;
|
||||||
video_notes_manager_.reset();
|
video_notes_manager_.reset();
|
||||||
@ -3776,8 +3779,6 @@ void Td::clear() {
|
|||||||
LOG(DEBUG) << "SecretChatsManager was cleared" << timer;
|
LOG(DEBUG) << "SecretChatsManager was cleared" << timer;
|
||||||
storage_manager_.reset();
|
storage_manager_.reset();
|
||||||
LOG(DEBUG) << "StorageManager was cleared" << timer;
|
LOG(DEBUG) << "StorageManager was cleared" << timer;
|
||||||
top_dialog_manager_.reset();
|
|
||||||
LOG(DEBUG) << "TopDialogManager was cleared" << timer;
|
|
||||||
verify_phone_number_manager_.reset();
|
verify_phone_number_manager_.reset();
|
||||||
LOG(DEBUG) << "VerifyPhoneNumberManager was cleared" << timer;
|
LOG(DEBUG) << "VerifyPhoneNumberManager was cleared" << timer;
|
||||||
|
|
||||||
@ -3823,6 +3824,8 @@ void Td::clear() {
|
|||||||
LOG(DEBUG) << "MemoryManager actor was cleared" << timer;
|
LOG(DEBUG) << "MemoryManager actor was cleared" << timer;
|
||||||
theme_manager_actor_.reset();
|
theme_manager_actor_.reset();
|
||||||
LOG(DEBUG) << "ThemeManager actor was cleared" << timer;
|
LOG(DEBUG) << "ThemeManager actor was cleared" << timer;
|
||||||
|
top_dialog_manager_actor_.reset();
|
||||||
|
LOG(DEBUG) << "TopDialogManager actor was cleared" << timer;
|
||||||
updates_manager_actor_.reset();
|
updates_manager_actor_.reset();
|
||||||
LOG(DEBUG) << "UpdatesManager actor was cleared" << timer;
|
LOG(DEBUG) << "UpdatesManager actor was cleared" << timer;
|
||||||
web_pages_manager_actor_.reset();
|
web_pages_manager_actor_.reset();
|
||||||
@ -4293,6 +4296,9 @@ void Td::init_managers() {
|
|||||||
theme_manager_ = make_unique<ThemeManager>(this, create_reference());
|
theme_manager_ = make_unique<ThemeManager>(this, create_reference());
|
||||||
theme_manager_actor_ = register_actor("ThemeManager", theme_manager_.get());
|
theme_manager_actor_ = register_actor("ThemeManager", theme_manager_.get());
|
||||||
G()->set_theme_manager(theme_manager_actor_.get());
|
G()->set_theme_manager(theme_manager_actor_.get());
|
||||||
|
top_dialog_manager_ = make_unique<TopDialogManager>(this, create_reference());
|
||||||
|
top_dialog_manager_actor_ = register_actor("TopDialogManager", top_dialog_manager_.get());
|
||||||
|
G()->set_top_dialog_manager(top_dialog_manager_actor_.get());
|
||||||
updates_manager_ = make_unique<UpdatesManager>(this, create_reference());
|
updates_manager_ = make_unique<UpdatesManager>(this, create_reference());
|
||||||
updates_manager_actor_ = register_actor("UpdatesManager", updates_manager_.get());
|
updates_manager_actor_ = register_actor("UpdatesManager", updates_manager_.get());
|
||||||
G()->set_updates_manager(updates_manager_actor_.get());
|
G()->set_updates_manager(updates_manager_actor_.get());
|
||||||
@ -4316,8 +4322,6 @@ void Td::init_managers() {
|
|||||||
secret_chats_manager_ = create_actor<SecretChatsManager>("SecretChatsManager", create_reference());
|
secret_chats_manager_ = create_actor<SecretChatsManager>("SecretChatsManager", create_reference());
|
||||||
G()->set_secret_chats_manager(secret_chats_manager_.get());
|
G()->set_secret_chats_manager(secret_chats_manager_.get());
|
||||||
secure_manager_ = create_actor<SecureManager>("SecureManager", create_reference());
|
secure_manager_ = create_actor<SecureManager>("SecureManager", create_reference());
|
||||||
top_dialog_manager_ = create_actor<TopDialogManager>("TopDialogManager", create_reference());
|
|
||||||
G()->set_top_dialog_manager(top_dialog_manager_.get());
|
|
||||||
verify_phone_number_manager_ = create_actor<PhoneNumberManager>(
|
verify_phone_number_manager_ = create_actor<PhoneNumberManager>(
|
||||||
"VerifyPhoneNumberManager", PhoneNumberManager::Type::VerifyPhone, create_reference());
|
"VerifyPhoneNumberManager", PhoneNumberManager::Type::VerifyPhone, create_reference());
|
||||||
}
|
}
|
||||||
@ -5239,14 +5243,8 @@ void Td::on_request(uint64 id, const td_api::setAutoDownloadSettings &request) {
|
|||||||
std::move(promise));
|
std::move(promise));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Td::on_request(uint64 id, td_api::getTopChats &request) {
|
void Td::on_request(uint64 id, const td_api::getTopChats &request) {
|
||||||
CHECK_IS_USER();
|
CHECK_IS_USER();
|
||||||
if (request.category_ == nullptr) {
|
|
||||||
return send_error_raw(id, 400, "Top chat category must be non-empty");
|
|
||||||
}
|
|
||||||
if (request.limit_ <= 0) {
|
|
||||||
return send_error_raw(id, 400, "Limit must be positive");
|
|
||||||
}
|
|
||||||
CREATE_REQUEST_PROMISE();
|
CREATE_REQUEST_PROMISE();
|
||||||
auto query_promise = PromiseCreator::lambda([promise = std::move(promise)](Result<vector<DialogId>> result) mutable {
|
auto query_promise = PromiseCreator::lambda([promise = std::move(promise)](Result<vector<DialogId>> result) mutable {
|
||||||
if (result.is_error()) {
|
if (result.is_error()) {
|
||||||
@ -5255,23 +5253,15 @@ void Td::on_request(uint64 id, td_api::getTopChats &request) {
|
|||||||
promise.set_value(MessagesManager::get_chats_object(-1, result.ok()));
|
promise.set_value(MessagesManager::get_chats_object(-1, result.ok()));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
send_closure(top_dialog_manager_, &TopDialogManager::get_top_dialogs, get_top_dialog_category(*request.category_),
|
top_dialog_manager_->get_top_dialogs(get_top_dialog_category(request.category_), request.limit_,
|
||||||
narrow_cast<size_t>(request.limit_), std::move(query_promise));
|
std::move(query_promise));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Td::on_request(uint64 id, const td_api::removeTopChat &request) {
|
void Td::on_request(uint64 id, const td_api::removeTopChat &request) {
|
||||||
CHECK_IS_USER();
|
CHECK_IS_USER();
|
||||||
if (request.category_ == nullptr) {
|
CREATE_OK_REQUEST_PROMISE();
|
||||||
return send_error_raw(id, 400, "Top chat category must be non-empty");
|
top_dialog_manager_->remove_dialog(get_top_dialog_category(request.category_), DialogId(request.chat_id_),
|
||||||
}
|
std::move(promise));
|
||||||
|
|
||||||
DialogId dialog_id(request.chat_id_);
|
|
||||||
if (!dialog_id.is_valid()) {
|
|
||||||
return send_error_raw(id, 400, "Invalid chat identifier");
|
|
||||||
}
|
|
||||||
send_closure(top_dialog_manager_, &TopDialogManager::remove_dialog, get_top_dialog_category(*request.category_),
|
|
||||||
dialog_id, messages_manager_->get_input_peer(dialog_id, AccessRights::Read));
|
|
||||||
send_closure(actor_id(this), &Td::send_result, id, td_api::make_object<td_api::ok>());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Td::on_request(uint64 id, const td_api::loadChats &request) {
|
void Td::on_request(uint64 id, const td_api::loadChats &request) {
|
||||||
|
@ -185,6 +185,8 @@ class Td final : public Actor {
|
|||||||
ActorOwn<StickersManager> stickers_manager_actor_;
|
ActorOwn<StickersManager> stickers_manager_actor_;
|
||||||
unique_ptr<ThemeManager> theme_manager_;
|
unique_ptr<ThemeManager> theme_manager_;
|
||||||
ActorOwn<ThemeManager> theme_manager_actor_;
|
ActorOwn<ThemeManager> theme_manager_actor_;
|
||||||
|
unique_ptr<TopDialogManager> top_dialog_manager_;
|
||||||
|
ActorOwn<TopDialogManager> top_dialog_manager_actor_;
|
||||||
unique_ptr<UpdatesManager> updates_manager_;
|
unique_ptr<UpdatesManager> updates_manager_;
|
||||||
ActorOwn<UpdatesManager> updates_manager_actor_;
|
ActorOwn<UpdatesManager> updates_manager_actor_;
|
||||||
unique_ptr<MemoryManager> memory_manager_;
|
unique_ptr<MemoryManager> memory_manager_;
|
||||||
@ -206,7 +208,6 @@ class Td final : public Actor {
|
|||||||
ActorOwn<SecretChatsManager> secret_chats_manager_;
|
ActorOwn<SecretChatsManager> secret_chats_manager_;
|
||||||
ActorOwn<StateManager> state_manager_;
|
ActorOwn<StateManager> state_manager_;
|
||||||
ActorOwn<StorageManager> storage_manager_;
|
ActorOwn<StorageManager> storage_manager_;
|
||||||
ActorOwn<TopDialogManager> top_dialog_manager_;
|
|
||||||
ActorOwn<PhoneNumberManager> verify_phone_number_manager_;
|
ActorOwn<PhoneNumberManager> verify_phone_number_manager_;
|
||||||
|
|
||||||
class ResultHandler : public std::enable_shared_from_this<ResultHandler> {
|
class ResultHandler : public std::enable_shared_from_this<ResultHandler> {
|
||||||
@ -564,7 +565,7 @@ class Td final : public Actor {
|
|||||||
|
|
||||||
void on_request(uint64 id, const td_api::setAutoDownloadSettings &request);
|
void on_request(uint64 id, const td_api::setAutoDownloadSettings &request);
|
||||||
|
|
||||||
void on_request(uint64 id, td_api::getTopChats &request);
|
void on_request(uint64 id, const td_api::getTopChats &request);
|
||||||
|
|
||||||
void on_request(uint64 id, const td_api::removeTopChat &request);
|
void on_request(uint64 id, const td_api::removeTopChat &request);
|
||||||
|
|
||||||
|
@ -352,6 +352,9 @@ Status TdDb::init_sqlite(int32 scheduler_id, const TdParameters ¶meters, DbK
|
|||||||
}
|
}
|
||||||
if (user_version == 0) {
|
if (user_version == 0) {
|
||||||
binlog_pmc.erase("next_contacts_sync_date");
|
binlog_pmc.erase("next_contacts_sync_date");
|
||||||
|
binlog_pmc.erase("saved_contact_count");
|
||||||
|
binlog_pmc.erase("old_featured_sticker_set_count");
|
||||||
|
binlog_pmc.erase("invalidate_old_featured_sticker_sets");
|
||||||
}
|
}
|
||||||
binlog_pmc.force_sync({});
|
binlog_pmc.force_sync({});
|
||||||
|
|
||||||
|
108
td/telegram/TopDialogCategory.cpp
Normal file
108
td/telegram/TopDialogCategory.cpp
Normal file
@ -0,0 +1,108 @@
|
|||||||
|
//
|
||||||
|
// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2021
|
||||||
|
//
|
||||||
|
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||||
|
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||||
|
//
|
||||||
|
#include "td/telegram/TopDialogCategory.h"
|
||||||
|
|
||||||
|
namespace td {
|
||||||
|
|
||||||
|
CSlice get_top_dialog_category_name(TopDialogCategory category) {
|
||||||
|
switch (category) {
|
||||||
|
case TopDialogCategory::Correspondent:
|
||||||
|
return CSlice("correspondent");
|
||||||
|
case TopDialogCategory::BotPM:
|
||||||
|
return CSlice("bot_pm");
|
||||||
|
case TopDialogCategory::BotInline:
|
||||||
|
return CSlice("bot_inline");
|
||||||
|
case TopDialogCategory::Group:
|
||||||
|
return CSlice("group");
|
||||||
|
case TopDialogCategory::Channel:
|
||||||
|
return CSlice("channel");
|
||||||
|
case TopDialogCategory::Call:
|
||||||
|
return CSlice("call");
|
||||||
|
case TopDialogCategory::ForwardUsers:
|
||||||
|
return CSlice("forward_users");
|
||||||
|
case TopDialogCategory::ForwardChats:
|
||||||
|
return CSlice("forward_chats");
|
||||||
|
default:
|
||||||
|
UNREACHABLE();
|
||||||
|
return CSlice();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TopDialogCategory get_top_dialog_category(const td_api::object_ptr<td_api::TopChatCategory> &category) {
|
||||||
|
if (category == nullptr) {
|
||||||
|
return TopDialogCategory::Size;
|
||||||
|
}
|
||||||
|
switch (category->get_id()) {
|
||||||
|
case td_api::topChatCategoryUsers::ID:
|
||||||
|
return TopDialogCategory::Correspondent;
|
||||||
|
case td_api::topChatCategoryBots::ID:
|
||||||
|
return TopDialogCategory::BotPM;
|
||||||
|
case td_api::topChatCategoryInlineBots::ID:
|
||||||
|
return TopDialogCategory::BotInline;
|
||||||
|
case td_api::topChatCategoryGroups::ID:
|
||||||
|
return TopDialogCategory::Group;
|
||||||
|
case td_api::topChatCategoryChannels::ID:
|
||||||
|
return TopDialogCategory::Channel;
|
||||||
|
case td_api::topChatCategoryCalls::ID:
|
||||||
|
return TopDialogCategory::Call;
|
||||||
|
case td_api::topChatCategoryForwardChats::ID:
|
||||||
|
return TopDialogCategory::ForwardUsers;
|
||||||
|
default:
|
||||||
|
UNREACHABLE();
|
||||||
|
return TopDialogCategory::Size;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
TopDialogCategory get_top_dialog_category(const telegram_api::object_ptr<telegram_api::TopPeerCategory> &category) {
|
||||||
|
CHECK(category != nullptr);
|
||||||
|
switch (category->get_id()) {
|
||||||
|
case telegram_api::topPeerCategoryCorrespondents::ID:
|
||||||
|
return TopDialogCategory::Correspondent;
|
||||||
|
case telegram_api::topPeerCategoryBotsPM::ID:
|
||||||
|
return TopDialogCategory::BotPM;
|
||||||
|
case telegram_api::topPeerCategoryBotsInline::ID:
|
||||||
|
return TopDialogCategory::BotInline;
|
||||||
|
case telegram_api::topPeerCategoryGroups::ID:
|
||||||
|
return TopDialogCategory::Group;
|
||||||
|
case telegram_api::topPeerCategoryChannels::ID:
|
||||||
|
return TopDialogCategory::Channel;
|
||||||
|
case telegram_api::topPeerCategoryPhoneCalls::ID:
|
||||||
|
return TopDialogCategory::Call;
|
||||||
|
case telegram_api::topPeerCategoryForwardUsers::ID:
|
||||||
|
return TopDialogCategory::ForwardUsers;
|
||||||
|
case telegram_api::topPeerCategoryForwardChats::ID:
|
||||||
|
return TopDialogCategory::ForwardChats;
|
||||||
|
default:
|
||||||
|
UNREACHABLE();
|
||||||
|
return TopDialogCategory::Size;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
telegram_api::object_ptr<telegram_api::TopPeerCategory> get_input_top_peer_category(TopDialogCategory category) {
|
||||||
|
switch (category) {
|
||||||
|
case TopDialogCategory::Correspondent:
|
||||||
|
return make_tl_object<telegram_api::topPeerCategoryCorrespondents>();
|
||||||
|
case TopDialogCategory::BotPM:
|
||||||
|
return make_tl_object<telegram_api::topPeerCategoryBotsPM>();
|
||||||
|
case TopDialogCategory::BotInline:
|
||||||
|
return make_tl_object<telegram_api::topPeerCategoryBotsInline>();
|
||||||
|
case TopDialogCategory::Group:
|
||||||
|
return make_tl_object<telegram_api::topPeerCategoryGroups>();
|
||||||
|
case TopDialogCategory::Channel:
|
||||||
|
return make_tl_object<telegram_api::topPeerCategoryChannels>();
|
||||||
|
case TopDialogCategory::Call:
|
||||||
|
return make_tl_object<telegram_api::topPeerCategoryPhoneCalls>();
|
||||||
|
case TopDialogCategory::ForwardUsers:
|
||||||
|
return make_tl_object<telegram_api::topPeerCategoryForwardUsers>();
|
||||||
|
case TopDialogCategory::ForwardChats:
|
||||||
|
return make_tl_object<telegram_api::topPeerCategoryForwardChats>();
|
||||||
|
default:
|
||||||
|
UNREACHABLE();
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace td
|
@ -7,8 +7,10 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "td/telegram/td_api.h"
|
#include "td/telegram/td_api.h"
|
||||||
|
#include "td/telegram/telegram_api.h"
|
||||||
|
|
||||||
#include "td/utils/common.h"
|
#include "td/utils/common.h"
|
||||||
|
#include "td/utils/Slice.h"
|
||||||
|
|
||||||
namespace td {
|
namespace td {
|
||||||
|
|
||||||
@ -24,25 +26,12 @@ enum class TopDialogCategory : int32 {
|
|||||||
Size
|
Size
|
||||||
};
|
};
|
||||||
|
|
||||||
inline TopDialogCategory get_top_dialog_category(const td_api::TopChatCategory &category) {
|
CSlice get_top_dialog_category_name(TopDialogCategory category);
|
||||||
switch (category.get_id()) {
|
|
||||||
case td_api::topChatCategoryUsers::ID:
|
TopDialogCategory get_top_dialog_category(const td_api::object_ptr<td_api::TopChatCategory> &category);
|
||||||
return TopDialogCategory::Correspondent;
|
|
||||||
case td_api::topChatCategoryBots::ID:
|
TopDialogCategory get_top_dialog_category(const telegram_api::object_ptr<telegram_api::TopPeerCategory> &category);
|
||||||
return TopDialogCategory::BotPM;
|
|
||||||
case td_api::topChatCategoryInlineBots::ID:
|
telegram_api::object_ptr<telegram_api::TopPeerCategory> get_input_top_peer_category(TopDialogCategory category);
|
||||||
return TopDialogCategory::BotInline;
|
|
||||||
case td_api::topChatCategoryGroups::ID:
|
|
||||||
return TopDialogCategory::Group;
|
|
||||||
case td_api::topChatCategoryChannels::ID:
|
|
||||||
return TopDialogCategory::Channel;
|
|
||||||
case td_api::topChatCategoryCalls::ID:
|
|
||||||
return TopDialogCategory::Call;
|
|
||||||
case td_api::topChatCategoryForwardChats::ID:
|
|
||||||
return TopDialogCategory::ForwardUsers;
|
|
||||||
default:
|
|
||||||
UNREACHABLE();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace td
|
} // namespace td
|
||||||
|
@ -6,6 +6,7 @@
|
|||||||
//
|
//
|
||||||
#include "td/telegram/TopDialogManager.h"
|
#include "td/telegram/TopDialogManager.h"
|
||||||
|
|
||||||
|
#include "td/telegram/AccessRights.h"
|
||||||
#include "td/telegram/AuthManager.h"
|
#include "td/telegram/AuthManager.h"
|
||||||
#include "td/telegram/ConfigShared.h"
|
#include "td/telegram/ConfigShared.h"
|
||||||
#include "td/telegram/ContactsManager.h"
|
#include "td/telegram/ContactsManager.h"
|
||||||
@ -23,6 +24,7 @@
|
|||||||
#include "td/telegram/telegram_api.h"
|
#include "td/telegram/telegram_api.h"
|
||||||
|
|
||||||
#include "td/utils/algorithm.h"
|
#include "td/utils/algorithm.h"
|
||||||
|
#include "td/utils/buffer.h"
|
||||||
#include "td/utils/logging.h"
|
#include "td/utils/logging.h"
|
||||||
#include "td/utils/misc.h"
|
#include "td/utils/misc.h"
|
||||||
#include "td/utils/port/Clocks.h"
|
#include "td/utils/port/Clocks.h"
|
||||||
@ -38,78 +40,97 @@
|
|||||||
|
|
||||||
namespace td {
|
namespace td {
|
||||||
|
|
||||||
static CSlice top_dialog_category_name(TopDialogCategory category) {
|
class GetTopPeersQuery final : public Td::ResultHandler {
|
||||||
switch (category) {
|
Promise<telegram_api::object_ptr<telegram_api::contacts_TopPeers>> promise_;
|
||||||
case TopDialogCategory::Correspondent:
|
|
||||||
return CSlice("correspondent");
|
|
||||||
case TopDialogCategory::BotPM:
|
|
||||||
return CSlice("bot_pm");
|
|
||||||
case TopDialogCategory::BotInline:
|
|
||||||
return CSlice("bot_inline");
|
|
||||||
case TopDialogCategory::Group:
|
|
||||||
return CSlice("group");
|
|
||||||
case TopDialogCategory::Channel:
|
|
||||||
return CSlice("channel");
|
|
||||||
case TopDialogCategory::Call:
|
|
||||||
return CSlice("call");
|
|
||||||
case TopDialogCategory::ForwardUsers:
|
|
||||||
return CSlice("forward_users");
|
|
||||||
case TopDialogCategory::ForwardChats:
|
|
||||||
return CSlice("forward_chats");
|
|
||||||
default:
|
|
||||||
UNREACHABLE();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static TopDialogCategory get_top_dialog_category(const telegram_api::TopPeerCategory &category) {
|
public:
|
||||||
switch (category.get_id()) {
|
explicit GetTopPeersQuery(Promise<telegram_api::object_ptr<telegram_api::contacts_TopPeers>> &&promise)
|
||||||
case telegram_api::topPeerCategoryCorrespondents::ID:
|
: promise_(std::move(promise)) {
|
||||||
return TopDialogCategory::Correspondent;
|
|
||||||
case telegram_api::topPeerCategoryBotsPM::ID:
|
|
||||||
return TopDialogCategory::BotPM;
|
|
||||||
case telegram_api::topPeerCategoryBotsInline::ID:
|
|
||||||
return TopDialogCategory::BotInline;
|
|
||||||
case telegram_api::topPeerCategoryGroups::ID:
|
|
||||||
return TopDialogCategory::Group;
|
|
||||||
case telegram_api::topPeerCategoryChannels::ID:
|
|
||||||
return TopDialogCategory::Channel;
|
|
||||||
case telegram_api::topPeerCategoryPhoneCalls::ID:
|
|
||||||
return TopDialogCategory::Call;
|
|
||||||
case telegram_api::topPeerCategoryForwardUsers::ID:
|
|
||||||
return TopDialogCategory::ForwardUsers;
|
|
||||||
case telegram_api::topPeerCategoryForwardChats::ID:
|
|
||||||
return TopDialogCategory::ForwardChats;
|
|
||||||
default:
|
|
||||||
UNREACHABLE();
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
static tl_object_ptr<telegram_api::TopPeerCategory> get_top_peer_category(TopDialogCategory category) {
|
void send(int64 hash) {
|
||||||
switch (category) {
|
int32 flags =
|
||||||
case TopDialogCategory::Correspondent:
|
telegram_api::contacts_getTopPeers::CORRESPONDENTS_MASK | telegram_api::contacts_getTopPeers::BOTS_PM_MASK |
|
||||||
return make_tl_object<telegram_api::topPeerCategoryCorrespondents>();
|
telegram_api::contacts_getTopPeers::BOTS_INLINE_MASK | telegram_api::contacts_getTopPeers::GROUPS_MASK |
|
||||||
case TopDialogCategory::BotPM:
|
telegram_api::contacts_getTopPeers::CHANNELS_MASK | telegram_api::contacts_getTopPeers::PHONE_CALLS_MASK |
|
||||||
return make_tl_object<telegram_api::topPeerCategoryBotsPM>();
|
telegram_api::contacts_getTopPeers::FORWARD_USERS_MASK | telegram_api::contacts_getTopPeers::FORWARD_CHATS_MASK;
|
||||||
case TopDialogCategory::BotInline:
|
send_query(G()->net_query_creator().create(telegram_api::contacts_getTopPeers(
|
||||||
return make_tl_object<telegram_api::topPeerCategoryBotsInline>();
|
flags, false /*ignored*/, false /*ignored*/, false /*ignored*/, false /*ignored*/, false /*ignored*/,
|
||||||
case TopDialogCategory::Group:
|
false /*ignored*/, false /*ignored*/, false /*ignored*/, 0 /*offset*/, 100 /*limit*/, hash)));
|
||||||
return make_tl_object<telegram_api::topPeerCategoryGroups>();
|
|
||||||
case TopDialogCategory::Channel:
|
|
||||||
return make_tl_object<telegram_api::topPeerCategoryChannels>();
|
|
||||||
case TopDialogCategory::Call:
|
|
||||||
return make_tl_object<telegram_api::topPeerCategoryPhoneCalls>();
|
|
||||||
case TopDialogCategory::ForwardUsers:
|
|
||||||
return make_tl_object<telegram_api::topPeerCategoryForwardUsers>();
|
|
||||||
case TopDialogCategory::ForwardChats:
|
|
||||||
return make_tl_object<telegram_api::topPeerCategoryForwardChats>();
|
|
||||||
default:
|
|
||||||
UNREACHABLE();
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
void on_result(uint64 id, BufferSlice packet) final {
|
||||||
|
auto result_ptr = fetch_result<telegram_api::contacts_getTopPeers>(packet);
|
||||||
|
if (result_ptr.is_error()) {
|
||||||
|
return on_error(id, result_ptr.move_as_error());
|
||||||
|
}
|
||||||
|
|
||||||
|
promise_.set_value(result_ptr.move_as_ok());
|
||||||
|
}
|
||||||
|
|
||||||
|
void on_error(uint64 id, Status status) final {
|
||||||
|
promise_.set_error(std::move(status));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class ToggleTopPeersQuery final : public Td::ResultHandler {
|
||||||
|
Promise<Unit> promise_;
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit ToggleTopPeersQuery(Promise<Unit> &&promise) : promise_(std::move(promise)) {
|
||||||
|
}
|
||||||
|
|
||||||
|
void send(bool is_enabled) {
|
||||||
|
send_query(G()->net_query_creator().create(telegram_api::contacts_toggleTopPeers(is_enabled)));
|
||||||
|
}
|
||||||
|
|
||||||
|
void on_result(uint64 id, BufferSlice packet) final {
|
||||||
|
auto result_ptr = fetch_result<telegram_api::contacts_toggleTopPeers>(packet);
|
||||||
|
if (result_ptr.is_error()) {
|
||||||
|
return on_error(id, result_ptr.move_as_error());
|
||||||
|
}
|
||||||
|
|
||||||
|
promise_.set_value(Unit());
|
||||||
|
}
|
||||||
|
|
||||||
|
void on_error(uint64 id, Status status) final {
|
||||||
|
promise_.set_error(std::move(status));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class ResetTopPeerRatingQuery final : public Td::ResultHandler {
|
||||||
|
DialogId dialog_id_;
|
||||||
|
|
||||||
|
public:
|
||||||
|
void send(TopDialogCategory category, DialogId dialog_id) {
|
||||||
|
auto input_peer = td->messages_manager_->get_input_peer(dialog_id, AccessRights::Read);
|
||||||
|
if (input_peer == nullptr) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
dialog_id_ = dialog_id;
|
||||||
|
send_query(G()->net_query_creator().create(
|
||||||
|
telegram_api::contacts_resetTopPeerRating(get_input_top_peer_category(category), std::move(input_peer))));
|
||||||
|
}
|
||||||
|
|
||||||
|
void on_result(uint64 id, BufferSlice packet) final {
|
||||||
|
auto result_ptr = fetch_result<telegram_api::contacts_resetTopPeerRating>(packet);
|
||||||
|
if (result_ptr.is_error()) {
|
||||||
|
return on_error(id, result_ptr.move_as_error());
|
||||||
|
}
|
||||||
|
|
||||||
|
// ignore the result
|
||||||
|
}
|
||||||
|
|
||||||
|
void on_error(uint64 id, Status status) final {
|
||||||
|
if (!td->messages_manager_->on_get_dialog_error(dialog_id_, status, "ResetTopPeerRatingQuery")) {
|
||||||
|
LOG(INFO) << "Receive error for resetTopPeerRating: " << status;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
void TopDialogManager::update_is_enabled(bool is_enabled) {
|
void TopDialogManager::update_is_enabled(bool is_enabled) {
|
||||||
auto auth_manager = G()->td().get_actor_unsafe()->auth_manager_.get();
|
if (td_->auth_manager_ == nullptr || !td_->auth_manager_->is_authorized() || td_->auth_manager_->is_bot()) {
|
||||||
if (auth_manager == nullptr || !auth_manager->is_authorized() || auth_manager->is_bot()) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -128,11 +149,15 @@ bool TopDialogManager::set_is_enabled(bool is_enabled) {
|
|||||||
|
|
||||||
LOG(DEBUG) << "Change top chats is_enabled to " << is_enabled;
|
LOG(DEBUG) << "Change top chats is_enabled to " << is_enabled;
|
||||||
is_enabled_ = is_enabled;
|
is_enabled_ = is_enabled;
|
||||||
init();
|
try_start();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TopDialogManager::send_toggle_top_peers(bool is_enabled) {
|
void TopDialogManager::send_toggle_top_peers(bool is_enabled) {
|
||||||
|
if (G()->close_flag()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (have_toggle_top_peers_query_) {
|
if (have_toggle_top_peers_query_) {
|
||||||
have_pending_toggle_top_peers_query_ = true;
|
have_pending_toggle_top_peers_query_ = true;
|
||||||
pending_toggle_top_peers_query_ = is_enabled;
|
pending_toggle_top_peers_query_ = is_enabled;
|
||||||
@ -141,9 +166,32 @@ void TopDialogManager::send_toggle_top_peers(bool is_enabled) {
|
|||||||
|
|
||||||
LOG(DEBUG) << "Send toggle top peers query to " << is_enabled;
|
LOG(DEBUG) << "Send toggle top peers query to " << is_enabled;
|
||||||
have_toggle_top_peers_query_ = true;
|
have_toggle_top_peers_query_ = true;
|
||||||
toggle_top_peers_query_is_enabled_ = is_enabled;
|
|
||||||
auto net_query = G()->net_query_creator().create(telegram_api::contacts_toggleTopPeers(is_enabled));
|
auto promise = PromiseCreator::lambda([actor_id = actor_id(this), is_enabled](Result<Unit> result) {
|
||||||
G()->net_query_dispatcher().dispatch_with_callback(std::move(net_query), actor_shared(this, 2));
|
send_closure(actor_id, &TopDialogManager::on_toggle_top_peers, is_enabled, std::move(result));
|
||||||
|
});
|
||||||
|
td_->create_handler<ToggleTopPeersQuery>(std::move(promise))->send(is_enabled);
|
||||||
|
}
|
||||||
|
|
||||||
|
void TopDialogManager::on_toggle_top_peers(bool is_enabled, Result<Unit> &&result) {
|
||||||
|
CHECK(have_toggle_top_peers_query_);
|
||||||
|
have_toggle_top_peers_query_ = false;
|
||||||
|
|
||||||
|
if (have_pending_toggle_top_peers_query_) {
|
||||||
|
have_pending_toggle_top_peers_query_ = false;
|
||||||
|
if (pending_toggle_top_peers_query_ != is_enabled) {
|
||||||
|
send_toggle_top_peers(pending_toggle_top_peers_query_);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result.is_ok()) {
|
||||||
|
// everything is synchronized
|
||||||
|
G()->td_db()->get_binlog_pmc()->erase("top_peers_enabled");
|
||||||
|
} else {
|
||||||
|
// let's resend the query forever
|
||||||
|
send_toggle_top_peers(is_enabled);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void TopDialogManager::on_dialog_used(TopDialogCategory category, DialogId dialog_id, int32 date) {
|
void TopDialogManager::on_dialog_used(TopDialogCategory category, DialogId dialog_id, int32 date) {
|
||||||
@ -175,7 +223,7 @@ void TopDialogManager::on_dialog_used(TopDialogCategory category, DialogId dialo
|
|||||||
it = next;
|
it = next;
|
||||||
}
|
}
|
||||||
|
|
||||||
LOG(INFO) << "Update " << top_dialog_category_name(category) << " rating of " << dialog_id << " by " << delta;
|
LOG(INFO) << "Update " << get_top_dialog_category_name(category) << " rating of " << dialog_id << " by " << delta;
|
||||||
|
|
||||||
if (!first_unsync_change_) {
|
if (!first_unsync_change_) {
|
||||||
first_unsync_change_ = Timestamp::now_cached();
|
first_unsync_change_ = Timestamp::now_cached();
|
||||||
@ -183,12 +231,16 @@ void TopDialogManager::on_dialog_used(TopDialogCategory category, DialogId dialo
|
|||||||
loop();
|
loop();
|
||||||
}
|
}
|
||||||
|
|
||||||
void TopDialogManager::remove_dialog(TopDialogCategory category, DialogId dialog_id,
|
void TopDialogManager::remove_dialog(TopDialogCategory category, DialogId dialog_id, Promise<Unit> &&promise) {
|
||||||
tl_object_ptr<telegram_api::InputPeer> input_peer) {
|
if (category == TopDialogCategory::Size) {
|
||||||
if (!is_active_ || !is_enabled_) {
|
return promise.set_error(Status::Error(400, "Top chat category must be non-empty"));
|
||||||
return;
|
}
|
||||||
|
if (!td_->messages_manager_->have_dialog_force(dialog_id, "remove_dialog")) {
|
||||||
|
return promise.set_error(Status::Error(400, "Chat not found"));
|
||||||
|
}
|
||||||
|
if (!is_active_ || !is_enabled_) {
|
||||||
|
return promise.set_value(Unit());
|
||||||
}
|
}
|
||||||
CHECK(dialog_id.is_valid());
|
|
||||||
|
|
||||||
if (category == TopDialogCategory::ForwardUsers && dialog_id.get_type() != DialogType::User) {
|
if (category == TopDialogCategory::ForwardUsers && dialog_id.get_type() != DialogType::User) {
|
||||||
category = TopDialogCategory::ForwardChats;
|
category = TopDialogCategory::ForwardChats;
|
||||||
@ -198,18 +250,12 @@ void TopDialogManager::remove_dialog(TopDialogCategory category, DialogId dialog
|
|||||||
CHECK(pos < by_category_.size());
|
CHECK(pos < by_category_.size());
|
||||||
auto &top_dialogs = by_category_[pos];
|
auto &top_dialogs = by_category_[pos];
|
||||||
|
|
||||||
LOG(INFO) << "Remove " << top_dialog_category_name(category) << " rating of " << dialog_id;
|
td_->create_handler<ResetTopPeerRatingQuery>()->send(category, dialog_id);
|
||||||
|
|
||||||
if (input_peer != nullptr) {
|
|
||||||
auto query = telegram_api::contacts_resetTopPeerRating(get_top_peer_category(category), std::move(input_peer));
|
|
||||||
auto net_query = G()->net_query_creator().create(query);
|
|
||||||
G()->net_query_dispatcher().dispatch_with_callback(std::move(net_query), actor_shared(this, 1));
|
|
||||||
}
|
|
||||||
|
|
||||||
auto it = std::find_if(top_dialogs.dialogs.begin(), top_dialogs.dialogs.end(),
|
auto it = std::find_if(top_dialogs.dialogs.begin(), top_dialogs.dialogs.end(),
|
||||||
[&](auto &top_dialog) { return top_dialog.dialog_id == dialog_id; });
|
[&](auto &top_dialog) { return top_dialog.dialog_id == dialog_id; });
|
||||||
if (it == top_dialogs.dialogs.end()) {
|
if (it == top_dialogs.dialogs.end()) {
|
||||||
return;
|
return promise.set_value(Unit());
|
||||||
}
|
}
|
||||||
|
|
||||||
top_dialogs.is_dirty = true;
|
top_dialogs.is_dirty = true;
|
||||||
@ -218,21 +264,26 @@ void TopDialogManager::remove_dialog(TopDialogCategory category, DialogId dialog
|
|||||||
first_unsync_change_ = Timestamp::now_cached();
|
first_unsync_change_ = Timestamp::now_cached();
|
||||||
}
|
}
|
||||||
loop();
|
loop();
|
||||||
|
promise.set_value(Unit());
|
||||||
}
|
}
|
||||||
|
|
||||||
void TopDialogManager::get_top_dialogs(TopDialogCategory category, size_t limit, Promise<vector<DialogId>> promise) {
|
void TopDialogManager::get_top_dialogs(TopDialogCategory category, int32 limit, Promise<vector<DialogId>> promise) {
|
||||||
|
if (category == TopDialogCategory::Size) {
|
||||||
|
return promise.set_error(Status::Error(400, "Top chat category must be non-empty"));
|
||||||
|
}
|
||||||
|
if (limit <= 0) {
|
||||||
|
return promise.set_error(Status::Error(400, "Limit must be positive"));
|
||||||
|
}
|
||||||
if (!is_active_) {
|
if (!is_active_) {
|
||||||
promise.set_error(Status::Error(400, "Not supported without chat info database"));
|
return promise.set_error(Status::Error(400, "Not supported without chat info database"));
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
if (!is_enabled_) {
|
if (!is_enabled_) {
|
||||||
promise.set_error(Status::Error(400, "Top chats computation is disabled"));
|
return promise.set_error(Status::Error(400, "Top chats computation is disabled"));
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
GetTopDialogsQuery query;
|
GetTopDialogsQuery query;
|
||||||
query.category = category;
|
query.category = category;
|
||||||
query.limit = limit;
|
query.limit = static_cast<size_t>(limit);
|
||||||
query.promise = std::move(promise);
|
query.promise = std::move(promise);
|
||||||
pending_get_top_dialogs_.push_back(std::move(query));
|
pending_get_top_dialogs_.push_back(std::move(query));
|
||||||
loop();
|
loop();
|
||||||
@ -315,24 +366,33 @@ void TopDialogManager::do_get_top_dialogs(GetTopDialogsQuery &&query) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
auto limit = std::min({query.limit, MAX_TOP_DIALOGS_LIMIT, dialog_ids.size()});
|
auto promise = PromiseCreator::lambda(
|
||||||
|
[actor_id = actor_id(this), query = std::move(query)](Result<vector<DialogId>> r_dialog_ids) mutable {
|
||||||
|
if (r_dialog_ids.is_error()) {
|
||||||
|
return query.promise.set_error(r_dialog_ids.move_as_error());
|
||||||
|
}
|
||||||
|
send_closure(actor_id, &TopDialogManager::on_load_dialogs, std::move(query), r_dialog_ids.move_as_ok());
|
||||||
|
});
|
||||||
|
td_->messages_manager_->load_dialogs(std::move(dialog_ids), std::move(promise));
|
||||||
|
}
|
||||||
|
|
||||||
auto promise = PromiseCreator::lambda([query = std::move(query), dialog_ids, limit](Result<Unit>) mutable {
|
void TopDialogManager::on_load_dialogs(GetTopDialogsQuery &&query, vector<DialogId> &&dialog_ids) {
|
||||||
|
auto limit = std::min({query.limit, MAX_TOP_DIALOGS_LIMIT, dialog_ids.size()});
|
||||||
vector<DialogId> result;
|
vector<DialogId> result;
|
||||||
result.reserve(limit);
|
result.reserve(limit);
|
||||||
for (auto dialog_id : dialog_ids) {
|
for (auto dialog_id : dialog_ids) {
|
||||||
if (dialog_id.get_type() == DialogType::User) {
|
if (dialog_id.get_type() == DialogType::User) {
|
||||||
auto user_id = dialog_id.get_user_id();
|
auto user_id = dialog_id.get_user_id();
|
||||||
if (G()->td().get_actor_unsafe()->contacts_manager_->is_user_deleted(user_id)) {
|
if (td_->contacts_manager_->is_user_deleted(user_id)) {
|
||||||
LOG(INFO) << "Skip deleted " << user_id;
|
LOG(INFO) << "Skip deleted " << user_id;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (G()->td().get_actor_unsafe()->contacts_manager_->get_my_id() == user_id) {
|
if (td_->contacts_manager_->get_my_id() == user_id) {
|
||||||
LOG(INFO) << "Skip self " << user_id;
|
LOG(INFO) << "Skip self " << user_id;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (query.category == TopDialogCategory::BotInline || query.category == TopDialogCategory::BotPM) {
|
if (query.category == TopDialogCategory::BotInline || query.category == TopDialogCategory::BotPM) {
|
||||||
auto r_bot_info = G()->td().get_actor_unsafe()->contacts_manager_->get_bot_data(user_id);
|
auto r_bot_info = td_->contacts_manager_->get_bot_data(user_id);
|
||||||
if (r_bot_info.is_error()) {
|
if (r_bot_info.is_error()) {
|
||||||
LOG(INFO) << "Skip not a bot " << user_id;
|
LOG(INFO) << "Skip not a bot " << user_id;
|
||||||
continue;
|
continue;
|
||||||
@ -352,126 +412,66 @@ void TopDialogManager::do_get_top_dialogs(GetTopDialogsQuery &&query) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
query.promise.set_value(std::move(result));
|
query.promise.set_value(std::move(result));
|
||||||
});
|
|
||||||
send_closure(G()->messages_manager(), &MessagesManager::load_dialogs, std::move(dialog_ids), std::move(promise));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void TopDialogManager::do_get_top_peers() {
|
void TopDialogManager::do_get_top_peers() {
|
||||||
LOG(INFO) << "Send get top peers request";
|
|
||||||
using telegram_api::contacts_getTopPeers;
|
|
||||||
|
|
||||||
std::vector<uint64> ids;
|
std::vector<uint64> ids;
|
||||||
for (auto &category : by_category_) {
|
for (auto &category : by_category_) {
|
||||||
for (auto &top_dialog : category.dialogs) {
|
for (auto &top_dialog : category.dialogs) {
|
||||||
auto dialog_id = top_dialog.dialog_id;
|
auto dialog_id = top_dialog.dialog_id;
|
||||||
switch (dialog_id.get_type()) {
|
switch (dialog_id.get_type()) {
|
||||||
case DialogType::Channel:
|
|
||||||
ids.push_back(dialog_id.get_channel_id().get());
|
|
||||||
break;
|
|
||||||
case DialogType::User:
|
case DialogType::User:
|
||||||
ids.push_back(dialog_id.get_user_id().get());
|
ids.push_back(dialog_id.get_user_id().get());
|
||||||
break;
|
break;
|
||||||
case DialogType::Chat:
|
case DialogType::Chat:
|
||||||
ids.push_back(dialog_id.get_chat_id().get());
|
ids.push_back(dialog_id.get_chat_id().get());
|
||||||
break;
|
break;
|
||||||
|
case DialogType::Channel:
|
||||||
|
ids.push_back(dialog_id.get_channel_id().get());
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
auto promise = PromiseCreator::lambda(
|
||||||
int64 hash = get_vector_hash(ids);
|
[actor_id = actor_id(this)](Result<telegram_api::object_ptr<telegram_api::contacts_TopPeers>> result) {
|
||||||
|
send_closure(actor_id, &TopDialogManager::on_get_top_peers, std::move(result));
|
||||||
int32 flags = contacts_getTopPeers::CORRESPONDENTS_MASK | contacts_getTopPeers::BOTS_PM_MASK |
|
});
|
||||||
contacts_getTopPeers::BOTS_INLINE_MASK | contacts_getTopPeers::GROUPS_MASK |
|
td_->create_handler<GetTopPeersQuery>(std::move(promise))->send(get_vector_hash(ids));
|
||||||
contacts_getTopPeers::CHANNELS_MASK | contacts_getTopPeers::PHONE_CALLS_MASK |
|
|
||||||
contacts_getTopPeers::FORWARD_USERS_MASK | contacts_getTopPeers::FORWARD_CHATS_MASK;
|
|
||||||
|
|
||||||
contacts_getTopPeers query{flags,
|
|
||||||
true /*correspondents*/,
|
|
||||||
true /*bot_pm*/,
|
|
||||||
true /*bot_inline */,
|
|
||||||
true /*phone_calls*/,
|
|
||||||
true /*groups*/,
|
|
||||||
true /*channels*/,
|
|
||||||
true /*forward_users*/,
|
|
||||||
true /*forward_chats*/,
|
|
||||||
0 /*offset*/,
|
|
||||||
100 /*limit*/,
|
|
||||||
hash};
|
|
||||||
auto net_query = G()->net_query_creator().create(query);
|
|
||||||
G()->net_query_dispatcher().dispatch_with_callback(std::move(net_query), actor_shared(this));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void TopDialogManager::on_result(NetQueryPtr net_query) {
|
void TopDialogManager::on_get_top_peers(Result<telegram_api::object_ptr<telegram_api::contacts_TopPeers>> result) {
|
||||||
auto query_type = get_link_token();
|
|
||||||
if (query_type == 2) { // toggleTopPeers
|
|
||||||
CHECK(have_toggle_top_peers_query_);
|
|
||||||
have_toggle_top_peers_query_ = false;
|
|
||||||
|
|
||||||
if (have_pending_toggle_top_peers_query_) {
|
|
||||||
have_pending_toggle_top_peers_query_ = false;
|
|
||||||
if (pending_toggle_top_peers_query_ != toggle_top_peers_query_is_enabled_) {
|
|
||||||
send_toggle_top_peers(pending_toggle_top_peers_query_);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
auto r_result = fetch_result<telegram_api::contacts_toggleTopPeers>(std::move(net_query));
|
|
||||||
if (r_result.is_ok()) {
|
|
||||||
// everything is synchronized
|
|
||||||
G()->td_db()->get_binlog_pmc()->erase("top_peers_enabled");
|
|
||||||
} else {
|
|
||||||
// let's resend the query forever
|
|
||||||
if (!G()->close_flag()) {
|
|
||||||
send_toggle_top_peers(toggle_top_peers_query_is_enabled_);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (query_type == 1) { // resetTopPeerRating
|
|
||||||
// ignore result
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
SCOPE_EXIT {
|
|
||||||
loop();
|
|
||||||
};
|
|
||||||
|
|
||||||
normalize_rating(); // once a day too
|
normalize_rating(); // once a day too
|
||||||
|
|
||||||
auto r_top_peers = fetch_result<telegram_api::contacts_getTopPeers>(std::move(net_query));
|
if (result.is_error()) {
|
||||||
if (r_top_peers.is_error()) {
|
|
||||||
last_server_sync_ = Timestamp::in(SERVER_SYNC_RESEND_DELAY - SERVER_SYNC_DELAY);
|
last_server_sync_ = Timestamp::in(SERVER_SYNC_RESEND_DELAY - SERVER_SYNC_DELAY);
|
||||||
|
loop();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
last_server_sync_ = Timestamp::now();
|
last_server_sync_ = Timestamp::now();
|
||||||
server_sync_state_ = SyncState::Ok;
|
server_sync_state_ = SyncState::Ok;
|
||||||
SCOPE_EXIT {
|
|
||||||
G()->td_db()->get_binlog_pmc()->set("top_dialogs_ts", to_string(static_cast<uint32>(Clocks::system())));
|
|
||||||
};
|
|
||||||
|
|
||||||
auto top_peers_parent = r_top_peers.move_as_ok();
|
auto top_peers_parent = result.move_as_ok();
|
||||||
LOG(DEBUG) << "Receive contacts_getTopPeers result: " << to_string(top_peers_parent);
|
LOG(DEBUG) << "Receive contacts_getTopPeers result: " << to_string(top_peers_parent);
|
||||||
switch (top_peers_parent->get_id()) {
|
switch (top_peers_parent->get_id()) {
|
||||||
case telegram_api::contacts_topPeersNotModified::ID:
|
case telegram_api::contacts_topPeersNotModified::ID:
|
||||||
// nothing to do
|
// nothing to do
|
||||||
return;
|
break;
|
||||||
case telegram_api::contacts_topPeersDisabled::ID:
|
case telegram_api::contacts_topPeersDisabled::ID:
|
||||||
G()->shared_config().set_option_boolean("disable_top_chats", true);
|
G()->shared_config().set_option_boolean("disable_top_chats", true);
|
||||||
set_is_enabled(false); // apply immediately
|
set_is_enabled(false); // apply immediately
|
||||||
return;
|
break;
|
||||||
case telegram_api::contacts_topPeers::ID: {
|
case telegram_api::contacts_topPeers::ID: {
|
||||||
G()->shared_config().set_option_empty("disable_top_chats");
|
G()->shared_config().set_option_empty("disable_top_chats");
|
||||||
set_is_enabled(true); // apply immediately
|
set_is_enabled(true); // apply immediately
|
||||||
auto top_peers = move_tl_object_as<telegram_api::contacts_topPeers>(std::move(top_peers_parent));
|
auto top_peers = move_tl_object_as<telegram_api::contacts_topPeers>(std::move(top_peers_parent));
|
||||||
|
|
||||||
send_closure(G()->contacts_manager(), &ContactsManager::on_get_users, std::move(top_peers->users_),
|
td_->contacts_manager_->on_get_users(std::move(top_peers->users_), "on get top chats");
|
||||||
"on get top chats");
|
td_->contacts_manager_->on_get_chats(std::move(top_peers->chats_), "on get top chats");
|
||||||
send_closure(G()->contacts_manager(), &ContactsManager::on_get_chats, std::move(top_peers->chats_),
|
|
||||||
"on get top chats");
|
|
||||||
for (auto &category : top_peers->categories_) {
|
for (auto &category : top_peers->categories_) {
|
||||||
auto dialog_category = get_top_dialog_category(*category->category_);
|
auto dialog_category = get_top_dialog_category(category->category_);
|
||||||
auto pos = static_cast<size_t>(dialog_category);
|
auto pos = static_cast<size_t>(dialog_category);
|
||||||
CHECK(pos < by_category_.size());
|
CHECK(pos < by_category_.size());
|
||||||
auto &top_dialogs = by_category_[pos];
|
auto &top_dialogs = by_category_[pos];
|
||||||
@ -491,13 +491,16 @@ void TopDialogManager::on_result(NetQueryPtr net_query) {
|
|||||||
default:
|
default:
|
||||||
UNREACHABLE();
|
UNREACHABLE();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
G()->td_db()->get_binlog_pmc()->set("top_dialogs_ts", to_string(static_cast<uint32>(Clocks::system())));
|
||||||
|
loop();
|
||||||
}
|
}
|
||||||
|
|
||||||
void TopDialogManager::do_save_top_dialogs() {
|
void TopDialogManager::do_save_top_dialogs() {
|
||||||
LOG(INFO) << "Save top chats";
|
LOG(INFO) << "Save top chats";
|
||||||
for (size_t top_dialog_category_i = 0; top_dialog_category_i < by_category_.size(); top_dialog_category_i++) {
|
for (size_t top_dialog_category_i = 0; top_dialog_category_i < by_category_.size(); top_dialog_category_i++) {
|
||||||
auto top_dialog_category = TopDialogCategory(top_dialog_category_i);
|
auto top_dialog_category = TopDialogCategory(top_dialog_category_i);
|
||||||
auto key = PSTRING() << "top_dialogs#" << top_dialog_category_name(top_dialog_category);
|
auto key = PSTRING() << "top_dialogs#" << get_top_dialog_category_name(top_dialog_category);
|
||||||
|
|
||||||
auto &top_dialogs = by_category_[top_dialog_category_i];
|
auto &top_dialogs = by_category_[top_dialog_category_i];
|
||||||
if (!top_dialogs.is_dirty) {
|
if (!top_dialogs.is_dirty) {
|
||||||
@ -512,16 +515,19 @@ void TopDialogManager::do_save_top_dialogs() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void TopDialogManager::start_up() {
|
void TopDialogManager::start_up() {
|
||||||
do_start_up();
|
init();
|
||||||
}
|
}
|
||||||
|
|
||||||
void TopDialogManager::do_start_up() {
|
void TopDialogManager::tear_down() {
|
||||||
auto auth_manager = G()->td().get_actor_unsafe()->auth_manager_.get();
|
parent_.reset();
|
||||||
if (auth_manager == nullptr || !auth_manager->is_authorized()) {
|
}
|
||||||
|
|
||||||
|
void TopDialogManager::init() {
|
||||||
|
if (td_->auth_manager_ == nullptr || !td_->auth_manager_->is_authorized()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
is_active_ = G()->parameters().use_chat_info_db && !auth_manager->is_bot();
|
is_active_ = G()->parameters().use_chat_info_db && !td_->auth_manager_->is_bot();
|
||||||
is_enabled_ = !G()->shared_config().get_option_boolean("disable_top_chats");
|
is_enabled_ = !G()->shared_config().get_option_boolean("disable_top_chats");
|
||||||
update_rating_e_decay();
|
update_rating_e_decay();
|
||||||
|
|
||||||
@ -530,11 +536,11 @@ void TopDialogManager::do_start_up() {
|
|||||||
send_toggle_top_peers(need_update_top_peers[0] == '1');
|
send_toggle_top_peers(need_update_top_peers[0] == '1');
|
||||||
}
|
}
|
||||||
|
|
||||||
init();
|
try_start();
|
||||||
loop();
|
loop();
|
||||||
}
|
}
|
||||||
|
|
||||||
void TopDialogManager::init() {
|
void TopDialogManager::try_start() {
|
||||||
was_first_sync_ = false;
|
was_first_sync_ = false;
|
||||||
first_unsync_change_ = Timestamp();
|
first_unsync_change_ = Timestamp();
|
||||||
server_sync_state_ = SyncState::None;
|
server_sync_state_ = SyncState::None;
|
||||||
@ -558,7 +564,7 @@ void TopDialogManager::init() {
|
|||||||
if (is_enabled_) {
|
if (is_enabled_) {
|
||||||
for (size_t top_dialog_category_i = 0; top_dialog_category_i < by_category_.size(); top_dialog_category_i++) {
|
for (size_t top_dialog_category_i = 0; top_dialog_category_i < by_category_.size(); top_dialog_category_i++) {
|
||||||
auto top_dialog_category = TopDialogCategory(top_dialog_category_i);
|
auto top_dialog_category = TopDialogCategory(top_dialog_category_i);
|
||||||
auto key = PSTRING() << "top_dialogs#" << top_dialog_category_name(top_dialog_category);
|
auto key = PSTRING() << "top_dialogs#" << get_top_dialog_category_name(top_dialog_category);
|
||||||
auto value = G()->td_db()->get_binlog_pmc()->get(key);
|
auto value = G()->td_db()->get_binlog_pmc()->get(key);
|
||||||
|
|
||||||
auto &top_dialogs = by_category_[top_dialog_category_i];
|
auto &top_dialogs = by_category_[top_dialog_category_i];
|
||||||
@ -585,9 +591,9 @@ void TopDialogManager::init() {
|
|||||||
|
|
||||||
void TopDialogManager::on_first_sync() {
|
void TopDialogManager::on_first_sync() {
|
||||||
was_first_sync_ = true;
|
was_first_sync_ = true;
|
||||||
if (!G()->close_flag() && G()->td().get_actor_unsafe()->auth_manager_->is_bot()) {
|
if (!G()->close_flag() && td_->auth_manager_->is_bot()) {
|
||||||
is_active_ = false;
|
is_active_ = false;
|
||||||
init();
|
try_start();
|
||||||
}
|
}
|
||||||
loop();
|
loop();
|
||||||
}
|
}
|
||||||
|
@ -7,8 +7,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "td/telegram/DialogId.h"
|
#include "td/telegram/DialogId.h"
|
||||||
#include "td/telegram/net/NetQuery.h"
|
|
||||||
#include "td/telegram/telegram_api.h"
|
|
||||||
#include "td/telegram/TopDialogCategory.h"
|
#include "td/telegram/TopDialogCategory.h"
|
||||||
|
|
||||||
#include "td/actor/actor.h"
|
#include "td/actor/actor.h"
|
||||||
@ -22,18 +20,20 @@
|
|||||||
|
|
||||||
namespace td {
|
namespace td {
|
||||||
|
|
||||||
class TopDialogManager final : public NetQueryCallback {
|
class Td;
|
||||||
|
|
||||||
|
class TopDialogManager final : public Actor {
|
||||||
public:
|
public:
|
||||||
explicit TopDialogManager(ActorShared<> parent) : parent_(std::move(parent)) {
|
TopDialogManager(Td *td, ActorShared<> parent) : td_(td), parent_(std::move(parent)) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void do_start_up();
|
void init();
|
||||||
|
|
||||||
void on_dialog_used(TopDialogCategory category, DialogId dialog_id, int32 date);
|
void on_dialog_used(TopDialogCategory category, DialogId dialog_id, int32 date);
|
||||||
|
|
||||||
void remove_dialog(TopDialogCategory category, DialogId dialog_id, tl_object_ptr<telegram_api::InputPeer> input_peer);
|
void remove_dialog(TopDialogCategory category, DialogId dialog_id, Promise<Unit> &&promise);
|
||||||
|
|
||||||
void get_top_dialogs(TopDialogCategory category, size_t limit, Promise<vector<DialogId>> promise);
|
void get_top_dialogs(TopDialogCategory category, int32 limit, Promise<vector<DialogId>> promise);
|
||||||
|
|
||||||
void update_rating_e_decay();
|
void update_rating_e_decay();
|
||||||
|
|
||||||
@ -44,14 +44,15 @@ class TopDialogManager final : public NetQueryCallback {
|
|||||||
static constexpr int32 SERVER_SYNC_DELAY = 86400; // seconds
|
static constexpr int32 SERVER_SYNC_DELAY = 86400; // seconds
|
||||||
static constexpr int32 SERVER_SYNC_RESEND_DELAY = 60; // seconds
|
static constexpr int32 SERVER_SYNC_RESEND_DELAY = 60; // seconds
|
||||||
static constexpr int32 DB_SYNC_DELAY = 5; // seconds
|
static constexpr int32 DB_SYNC_DELAY = 5; // seconds
|
||||||
|
|
||||||
|
Td *td_;
|
||||||
ActorShared<> parent_;
|
ActorShared<> parent_;
|
||||||
|
|
||||||
bool is_active_{false};
|
bool is_active_ = false;
|
||||||
bool is_enabled_{true};
|
bool is_enabled_ = true;
|
||||||
int32 rating_e_decay_ = 241920;
|
int32 rating_e_decay_ = 241920;
|
||||||
|
|
||||||
bool have_toggle_top_peers_query_ = false;
|
bool have_toggle_top_peers_query_ = false;
|
||||||
bool toggle_top_peers_query_is_enabled_ = false;
|
|
||||||
bool have_pending_toggle_top_peers_query_ = false;
|
bool have_pending_toggle_top_peers_query_ = false;
|
||||||
bool pending_toggle_top_peers_query_ = false;
|
bool pending_toggle_top_peers_query_ = false;
|
||||||
bool was_first_sync_{false};
|
bool was_first_sync_{false};
|
||||||
@ -97,21 +98,30 @@ class TopDialogManager final : public NetQueryCallback {
|
|||||||
void normalize_rating();
|
void normalize_rating();
|
||||||
|
|
||||||
bool set_is_enabled(bool is_enabled);
|
bool set_is_enabled(bool is_enabled);
|
||||||
|
|
||||||
void send_toggle_top_peers(bool is_enabled);
|
void send_toggle_top_peers(bool is_enabled);
|
||||||
|
|
||||||
|
void on_toggle_top_peers(bool is_enabled, Result<Unit> &&result);
|
||||||
|
|
||||||
void do_get_top_dialogs(GetTopDialogsQuery &&query);
|
void do_get_top_dialogs(GetTopDialogsQuery &&query);
|
||||||
|
|
||||||
|
void on_load_dialogs(GetTopDialogsQuery &&query, vector<DialogId> &&dialog_ids);
|
||||||
|
|
||||||
void do_get_top_peers();
|
void do_get_top_peers();
|
||||||
|
|
||||||
void do_save_top_dialogs();
|
void do_save_top_dialogs();
|
||||||
|
|
||||||
void on_first_sync();
|
void on_first_sync();
|
||||||
|
|
||||||
void on_result(NetQueryPtr net_query) final;
|
void on_get_top_peers(Result<telegram_api::object_ptr<telegram_api::contacts_TopPeers>> result);
|
||||||
|
|
||||||
void init();
|
void try_start();
|
||||||
|
|
||||||
void start_up() final;
|
void start_up() final;
|
||||||
|
|
||||||
void loop() final;
|
void loop() final;
|
||||||
|
|
||||||
|
void tear_down() final;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace td
|
} // namespace td
|
||||||
|
@ -2425,7 +2425,7 @@ class CliClient final : public Actor {
|
|||||||
td_api::make_object<td_api::addNetworkStatistics>(td_api::make_object<td_api::networkStatisticsEntryFile>(
|
td_api::make_object<td_api::addNetworkStatistics>(td_api::make_object<td_api::networkStatisticsEntryFile>(
|
||||||
td_api::make_object<td_api::fileTypeDocument>(), get_network_type(network_type), sent_bytes,
|
td_api::make_object<td_api::fileTypeDocument>(), get_network_type(network_type), sent_bytes,
|
||||||
received_bytes)));
|
received_bytes)));
|
||||||
} else if (op == "top_chats") {
|
} else if (op == "gtc") {
|
||||||
send_request(td_api::make_object<td_api::getTopChats>(get_top_chat_category(args), 50));
|
send_request(td_api::make_object<td_api::getTopChats>(get_top_chat_category(args), 50));
|
||||||
} else if (op == "rtc") {
|
} else if (op == "rtc") {
|
||||||
string chat_id;
|
string chat_id;
|
||||||
|
@ -82,9 +82,8 @@ void FileGcWorker::run_gc(const FileGcParameters ¶meters, std::vector<FullFi
|
|||||||
total_size += info.size;
|
total_size += info.size;
|
||||||
}
|
}
|
||||||
|
|
||||||
FileStats new_stats;
|
FileStats new_stats(false, parameters.dialog_limit != 0);
|
||||||
FileStats removed_stats;
|
FileStats removed_stats(false, parameters.dialog_limit != 0);
|
||||||
removed_stats.split_by_owner_dialog_id = new_stats.split_by_owner_dialog_id = parameters.dialog_limit != 0;
|
|
||||||
|
|
||||||
auto do_remove_file = [&removed_stats](const FullFileInfo &info) {
|
auto do_remove_file = [&removed_stats](const FullFileInfo &info) {
|
||||||
removed_stats.add_copy(info);
|
removed_stats.add_copy(info);
|
||||||
|
@ -17,7 +17,6 @@
|
|||||||
#include "td/telegram/files/FileLoadManager.h"
|
#include "td/telegram/files/FileLoadManager.h"
|
||||||
#include "td/telegram/files/FileLocation.h"
|
#include "td/telegram/files/FileLocation.h"
|
||||||
#include "td/telegram/files/FileSourceId.h"
|
#include "td/telegram/files/FileSourceId.h"
|
||||||
#include "td/telegram/files/FileStats.h"
|
|
||||||
#include "td/telegram/files/FileType.h"
|
#include "td/telegram/files/FileType.h"
|
||||||
#include "td/telegram/Location.h"
|
#include "td/telegram/Location.h"
|
||||||
#include "td/telegram/PhotoSizeSource.h"
|
#include "td/telegram/PhotoSizeSource.h"
|
||||||
|
@ -10,6 +10,7 @@
|
|||||||
|
|
||||||
#include "td/telegram/files/FileLoaderUtils.h"
|
#include "td/telegram/files/FileLoaderUtils.h"
|
||||||
|
|
||||||
|
#include "td/utils/algorithm.h"
|
||||||
#include "td/utils/common.h"
|
#include "td/utils/common.h"
|
||||||
#include "td/utils/format.h"
|
#include "td/utils/format.h"
|
||||||
#include "td/utils/misc.h"
|
#include "td/utils/misc.h"
|
||||||
@ -27,34 +28,34 @@ tl_object_ptr<td_api::storageStatisticsFast> FileStatsFast::get_storage_statisti
|
|||||||
|
|
||||||
void FileStats::add(StatByType &by_type, FileType file_type, int64 size) {
|
void FileStats::add(StatByType &by_type, FileType file_type, int64 size) {
|
||||||
auto pos = static_cast<size_t>(file_type);
|
auto pos = static_cast<size_t>(file_type);
|
||||||
CHECK(pos < stat_by_type.size());
|
CHECK(pos < stat_by_type_.size());
|
||||||
by_type[pos].size += size;
|
by_type[pos].size += size;
|
||||||
by_type[pos].cnt++;
|
by_type[pos].cnt++;
|
||||||
}
|
}
|
||||||
|
|
||||||
void FileStats::add_impl(const FullFileInfo &info) {
|
void FileStats::add_impl(const FullFileInfo &info) {
|
||||||
if (split_by_owner_dialog_id) {
|
if (split_by_owner_dialog_id_) {
|
||||||
add(stat_by_owner_dialog_id[info.owner_dialog_id], info.file_type, info.size);
|
add(stat_by_owner_dialog_id_[info.owner_dialog_id], info.file_type, info.size);
|
||||||
} else {
|
} else {
|
||||||
add(stat_by_type, info.file_type, info.size);
|
add(stat_by_type_, info.file_type, info.size);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void FileStats::add_copy(const FullFileInfo &info) {
|
void FileStats::add_copy(const FullFileInfo &info) {
|
||||||
add_impl(info);
|
add_impl(info);
|
||||||
if (need_all_files) {
|
if (need_all_files_) {
|
||||||
all_files.push_back(info);
|
all_files_.push_back(info);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void FileStats::add(FullFileInfo &&info) {
|
void FileStats::add(FullFileInfo &&info) {
|
||||||
add_impl(info);
|
add_impl(info);
|
||||||
if (need_all_files) {
|
if (need_all_files_) {
|
||||||
all_files.push_back(std::move(info));
|
all_files_.push_back(std::move(info));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
FileTypeStat get_nontemp_stat(const FileStats::StatByType &by_type) {
|
FileTypeStat FileStats::get_nontemp_stat(const FileStats::StatByType &by_type) {
|
||||||
FileTypeStat stat;
|
FileTypeStat stat;
|
||||||
for (int32 i = 0; i < MAX_FILE_TYPE; i++) {
|
for (int32 i = 0; i < MAX_FILE_TYPE; i++) {
|
||||||
if (FileType(i) != FileType::Temp) {
|
if (FileType(i) != FileType::Temp) {
|
||||||
@ -66,11 +67,11 @@ FileTypeStat get_nontemp_stat(const FileStats::StatByType &by_type) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
FileTypeStat FileStats::get_total_nontemp_stat() const {
|
FileTypeStat FileStats::get_total_nontemp_stat() const {
|
||||||
if (!split_by_owner_dialog_id) {
|
if (!split_by_owner_dialog_id_) {
|
||||||
return get_nontemp_stat(stat_by_type);
|
return get_nontemp_stat(stat_by_type_);
|
||||||
}
|
}
|
||||||
FileTypeStat stat;
|
FileTypeStat stat;
|
||||||
for (auto &dialog : stat_by_owner_dialog_id) {
|
for (auto &dialog : stat_by_owner_dialog_id_) {
|
||||||
auto tmp = get_nontemp_stat(dialog.second);
|
auto tmp = get_nontemp_stat(dialog.second);
|
||||||
stat.size += tmp.size;
|
stat.size += tmp.size;
|
||||||
stat.cnt += tmp.cnt;
|
stat.cnt += tmp.cnt;
|
||||||
@ -82,12 +83,12 @@ void FileStats::apply_dialog_limit(int32 limit) {
|
|||||||
if (limit == -1) {
|
if (limit == -1) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!split_by_owner_dialog_id) {
|
if (!split_by_owner_dialog_id_) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<std::pair<int64, DialogId>> dialogs;
|
std::vector<std::pair<int64, DialogId>> dialogs;
|
||||||
for (auto &dialog : stat_by_owner_dialog_id) {
|
for (auto &dialog : stat_by_owner_dialog_id_) {
|
||||||
if (!dialog.first.is_valid()) {
|
if (!dialog.first.is_valid()) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -105,15 +106,14 @@ void FileStats::apply_dialog_limit(int32 limit) {
|
|||||||
[](const auto &x, const auto &y) { return x.first > y.first; });
|
[](const auto &x, const auto &y) { return x.first > y.first; });
|
||||||
dialogs.resize(prefix);
|
dialogs.resize(prefix);
|
||||||
|
|
||||||
std::unordered_set<DialogId, DialogIdHash> all_dialogs;
|
apply_dialog_ids(transform(dialogs, [](const auto &dialog) { return dialog.second; }));
|
||||||
|
}
|
||||||
for (auto &dialog : dialogs) {
|
|
||||||
all_dialogs.insert(dialog.second);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
void FileStats::apply_dialog_ids(const vector<DialogId> &dialog_ids) {
|
||||||
|
std::unordered_set<DialogId, DialogIdHash> all_dialogs(dialog_ids.begin(), dialog_ids.end());
|
||||||
StatByType other_stats;
|
StatByType other_stats;
|
||||||
bool other_flag = false;
|
bool other_flag = false;
|
||||||
for (auto it = stat_by_owner_dialog_id.begin(); it != stat_by_owner_dialog_id.end();) {
|
for (auto it = stat_by_owner_dialog_id_.begin(); it != stat_by_owner_dialog_id_.end();) {
|
||||||
if (all_dialogs.count(it->first)) {
|
if (all_dialogs.count(it->first)) {
|
||||||
++it;
|
++it;
|
||||||
} else {
|
} else {
|
||||||
@ -122,24 +122,24 @@ void FileStats::apply_dialog_limit(int32 limit) {
|
|||||||
other_stats[i].cnt += it->second[i].cnt;
|
other_stats[i].cnt += it->second[i].cnt;
|
||||||
}
|
}
|
||||||
other_flag = true;
|
other_flag = true;
|
||||||
it = stat_by_owner_dialog_id.erase(it);
|
it = stat_by_owner_dialog_id_.erase(it);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (other_flag) {
|
if (other_flag) {
|
||||||
DialogId other_dialog_id;
|
DialogId other_dialog_id; // prevents MSVC warning C4709: comma operator within array index expression
|
||||||
stat_by_owner_dialog_id[other_dialog_id] = other_stats;
|
stat_by_owner_dialog_id_[other_dialog_id] = other_stats;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static tl_object_ptr<td_api::storageStatisticsByChat> get_storage_statistics_by_chat_object(
|
td_api::object_ptr<td_api::storageStatisticsByChat> FileStats::get_storage_statistics_by_chat_object(
|
||||||
DialogId dialog_id, const FileStats::StatByType &stat_by_type) {
|
DialogId dialog_id, const FileStats::StatByType &stat_by_type_) {
|
||||||
auto stats = make_tl_object<td_api::storageStatisticsByChat>(dialog_id.get(), 0, 0, Auto());
|
auto stats = make_tl_object<td_api::storageStatisticsByChat>(dialog_id.get(), 0, 0, Auto());
|
||||||
FileStats::StatByType aggregated_stats;
|
FileStats::StatByType aggregated_stats;
|
||||||
for (int32 i = 0; i < MAX_FILE_TYPE; i++) {
|
for (int32 i = 0; i < MAX_FILE_TYPE; i++) {
|
||||||
size_t file_type = narrow_cast<size_t>(get_main_file_type(static_cast<FileType>(i)));
|
size_t file_type = narrow_cast<size_t>(get_main_file_type(static_cast<FileType>(i)));
|
||||||
aggregated_stats[file_type].size += stat_by_type[i].size;
|
aggregated_stats[file_type].size += stat_by_type_[i].size;
|
||||||
aggregated_stats[file_type].cnt += stat_by_type[i].cnt;
|
aggregated_stats[file_type].cnt += stat_by_type_[i].cnt;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int32 i = 0; i < MAX_FILE_TYPE; i++) {
|
for (int32 i = 0; i < MAX_FILE_TYPE; i++) {
|
||||||
@ -161,12 +161,12 @@ static tl_object_ptr<td_api::storageStatisticsByChat> get_storage_statistics_by_
|
|||||||
|
|
||||||
tl_object_ptr<td_api::storageStatistics> FileStats::get_storage_statistics_object() const {
|
tl_object_ptr<td_api::storageStatistics> FileStats::get_storage_statistics_object() const {
|
||||||
auto stats = make_tl_object<td_api::storageStatistics>(0, 0, Auto());
|
auto stats = make_tl_object<td_api::storageStatistics>(0, 0, Auto());
|
||||||
if (!split_by_owner_dialog_id) {
|
if (!split_by_owner_dialog_id_) {
|
||||||
stats->by_chat_.reserve(1);
|
stats->by_chat_.reserve(1);
|
||||||
stats->by_chat_.push_back(get_storage_statistics_by_chat_object(DialogId(), stat_by_type));
|
stats->by_chat_.push_back(get_storage_statistics_by_chat_object(DialogId(), stat_by_type_));
|
||||||
} else {
|
} else {
|
||||||
stats->by_chat_.reserve(stat_by_owner_dialog_id.size());
|
stats->by_chat_.reserve(stat_by_owner_dialog_id_.size());
|
||||||
for (auto &by_dialog : stat_by_owner_dialog_id) {
|
for (auto &by_dialog : stat_by_owner_dialog_id_) {
|
||||||
stats->by_chat_.push_back(get_storage_statistics_by_chat_object(by_dialog.first, by_dialog.second));
|
stats->by_chat_.push_back(get_storage_statistics_by_chat_object(by_dialog.first, by_dialog.second));
|
||||||
}
|
}
|
||||||
std::sort(stats->by_chat_.begin(), stats->by_chat_.end(), [](const auto &x, const auto &y) {
|
std::sort(stats->by_chat_.begin(), stats->by_chat_.end(), [](const auto &x, const auto &y) {
|
||||||
@ -183,13 +183,13 @@ tl_object_ptr<td_api::storageStatistics> FileStats::get_storage_statistics_objec
|
|||||||
return stats;
|
return stats;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<DialogId> FileStats::get_dialog_ids() const {
|
vector<DialogId> FileStats::get_dialog_ids() const {
|
||||||
std::vector<DialogId> res;
|
vector<DialogId> res;
|
||||||
if (!split_by_owner_dialog_id) {
|
if (!split_by_owner_dialog_id_) {
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
res.reserve(stat_by_owner_dialog_id.size());
|
res.reserve(stat_by_owner_dialog_id_.size());
|
||||||
for (auto &by_dialog : stat_by_owner_dialog_id) {
|
for (auto &by_dialog : stat_by_owner_dialog_id_) {
|
||||||
if (by_dialog.first.is_valid()) {
|
if (by_dialog.first.is_valid()) {
|
||||||
res.push_back(by_dialog.first);
|
res.push_back(by_dialog.first);
|
||||||
}
|
}
|
||||||
@ -197,27 +197,31 @@ std::vector<DialogId> FileStats::get_dialog_ids() const {
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
StringBuilder &operator<<(StringBuilder &sb, const FileTypeStat &stat) {
|
vector<FullFileInfo> FileStats::get_all_files() {
|
||||||
|
return std::move(all_files_);
|
||||||
|
}
|
||||||
|
|
||||||
|
static StringBuilder &operator<<(StringBuilder &sb, const FileTypeStat &stat) {
|
||||||
return sb << tag("size", format::as_size(stat.size)) << tag("count", stat.cnt);
|
return sb << tag("size", format::as_size(stat.size)) << tag("count", stat.cnt);
|
||||||
}
|
}
|
||||||
|
|
||||||
StringBuilder &operator<<(StringBuilder &sb, const FileStats &file_stats) {
|
StringBuilder &operator<<(StringBuilder &sb, const FileStats &file_stats) {
|
||||||
if (!file_stats.split_by_owner_dialog_id) {
|
if (!file_stats.split_by_owner_dialog_id_) {
|
||||||
FileTypeStat total_stat;
|
FileTypeStat total_stat;
|
||||||
for (auto &type_stat : file_stats.stat_by_type) {
|
for (auto &type_stat : file_stats.stat_by_type_) {
|
||||||
total_stat.size += type_stat.size;
|
total_stat.size += type_stat.size;
|
||||||
total_stat.cnt += type_stat.cnt;
|
total_stat.cnt += type_stat.cnt;
|
||||||
}
|
}
|
||||||
|
|
||||||
sb << "[FileStat " << tag("total", total_stat);
|
sb << "[FileStat " << tag("total", total_stat);
|
||||||
for (int32 i = 0; i < MAX_FILE_TYPE; i++) {
|
for (int32 i = 0; i < MAX_FILE_TYPE; i++) {
|
||||||
sb << tag(get_file_type_name(FileType(i)), file_stats.stat_by_type[i]);
|
sb << tag(get_file_type_name(FileType(i)), file_stats.stat_by_type_[i]);
|
||||||
}
|
}
|
||||||
sb << "]";
|
sb << "]";
|
||||||
} else {
|
} else {
|
||||||
{
|
{
|
||||||
FileTypeStat total_stat;
|
FileTypeStat total_stat;
|
||||||
for (auto &by_type : file_stats.stat_by_owner_dialog_id) {
|
for (auto &by_type : file_stats.stat_by_owner_dialog_id_) {
|
||||||
for (auto &type_stat : by_type.second) {
|
for (auto &type_stat : by_type.second) {
|
||||||
total_stat.size += type_stat.size;
|
total_stat.size += type_stat.size;
|
||||||
total_stat.cnt += type_stat.cnt;
|
total_stat.cnt += type_stat.cnt;
|
||||||
@ -225,7 +229,7 @@ StringBuilder &operator<<(StringBuilder &sb, const FileStats &file_stats) {
|
|||||||
}
|
}
|
||||||
sb << "[FileStat " << tag("total", total_stat);
|
sb << "[FileStat " << tag("total", total_stat);
|
||||||
}
|
}
|
||||||
for (auto &by_type : file_stats.stat_by_owner_dialog_id) {
|
for (auto &by_type : file_stats.stat_by_owner_dialog_id_) {
|
||||||
FileTypeStat dialog_stat;
|
FileTypeStat dialog_stat;
|
||||||
for (auto &type_stat : by_type.second) {
|
for (auto &type_stat : by_type.second) {
|
||||||
dialog_stat.size += type_stat.size;
|
dialog_stat.size += type_stat.size;
|
||||||
|
@ -66,28 +66,47 @@ struct FileStatsFast {
|
|||||||
tl_object_ptr<td_api::storageStatisticsFast> get_storage_statistics_fast_object() const;
|
tl_object_ptr<td_api::storageStatisticsFast> get_storage_statistics_fast_object() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct FileStats {
|
class FileStats {
|
||||||
bool need_all_files{false};
|
bool need_all_files_{false};
|
||||||
bool split_by_owner_dialog_id{false};
|
bool split_by_owner_dialog_id_{false};
|
||||||
|
|
||||||
using StatByType = std::array<FileTypeStat, MAX_FILE_TYPE>;
|
using StatByType = std::array<FileTypeStat, MAX_FILE_TYPE>;
|
||||||
|
|
||||||
StatByType stat_by_type;
|
StatByType stat_by_type_;
|
||||||
std::unordered_map<DialogId, StatByType, DialogIdHash> stat_by_owner_dialog_id;
|
std::unordered_map<DialogId, StatByType, DialogIdHash> stat_by_owner_dialog_id_;
|
||||||
|
vector<FullFileInfo> all_files_;
|
||||||
|
|
||||||
std::vector<FullFileInfo> all_files;
|
void add_impl(const FullFileInfo &info);
|
||||||
|
|
||||||
|
void add(StatByType &by_type, FileType file_type, int64 size);
|
||||||
|
|
||||||
|
static FileTypeStat get_nontemp_stat(const StatByType &by_type);
|
||||||
|
|
||||||
|
static td_api::object_ptr<td_api::storageStatisticsByChat> get_storage_statistics_by_chat_object(
|
||||||
|
DialogId dialog_id, const StatByType &stat_by_type_);
|
||||||
|
|
||||||
|
friend StringBuilder &operator<<(StringBuilder &sb, const FileStats &file_stats);
|
||||||
|
|
||||||
|
public:
|
||||||
|
FileStats(bool need_all_files, bool split_by_owner_dialog_id)
|
||||||
|
: need_all_files_(need_all_files), split_by_owner_dialog_id_(split_by_owner_dialog_id) {
|
||||||
|
}
|
||||||
|
|
||||||
void add_copy(const FullFileInfo &info);
|
void add_copy(const FullFileInfo &info);
|
||||||
|
|
||||||
void add(FullFileInfo &&info);
|
void add(FullFileInfo &&info);
|
||||||
|
|
||||||
void apply_dialog_limit(int32 limit);
|
void apply_dialog_limit(int32 limit);
|
||||||
|
|
||||||
|
void apply_dialog_ids(const vector<DialogId> &dialog_ids);
|
||||||
|
|
||||||
tl_object_ptr<td_api::storageStatistics> get_storage_statistics_object() const;
|
tl_object_ptr<td_api::storageStatistics> get_storage_statistics_object() const;
|
||||||
std::vector<DialogId> get_dialog_ids() const;
|
|
||||||
|
vector<DialogId> get_dialog_ids() const;
|
||||||
|
|
||||||
FileTypeStat get_total_nontemp_stat() const;
|
FileTypeStat get_total_nontemp_stat() const;
|
||||||
|
|
||||||
private:
|
vector<FullFileInfo> get_all_files();
|
||||||
void add_impl(const FullFileInfo &info);
|
|
||||||
void add(StatByType &by_type, FileType file_type, int64 size);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
StringBuilder &operator<<(StringBuilder &sb, const FileStats &file_stats);
|
StringBuilder &operator<<(StringBuilder &sb, const FileStats &file_stats);
|
||||||
|
@ -147,8 +147,7 @@ void FileStatsWorker::get_stats(bool need_all_files, bool split_by_owner_dialog_
|
|||||||
split_by_owner_dialog_id = false;
|
split_by_owner_dialog_id = false;
|
||||||
}
|
}
|
||||||
if (!split_by_owner_dialog_id) {
|
if (!split_by_owner_dialog_id) {
|
||||||
FileStats file_stats;
|
FileStats file_stats(need_all_files, false);
|
||||||
file_stats.need_all_files = need_all_files;
|
|
||||||
auto start = Time::now();
|
auto start = Time::now();
|
||||||
scan_fs(token_, [&](FsFileInfo &fs_info) {
|
scan_fs(token_, [&](FsFileInfo &fs_info) {
|
||||||
FullFileInfo info;
|
FullFileInfo info;
|
||||||
@ -207,9 +206,7 @@ void FileStatsWorker::get_stats(bool need_all_files, bool split_by_owner_dialog_
|
|||||||
return promise.set_error(Status::Error(500, "Request aborted"));
|
return promise.set_error(Status::Error(500, "Request aborted"));
|
||||||
}
|
}
|
||||||
|
|
||||||
FileStats file_stats;
|
FileStats file_stats(need_all_files, split_by_owner_dialog_id);
|
||||||
file_stats.need_all_files = need_all_files;
|
|
||||||
file_stats.split_by_owner_dialog_id = split_by_owner_dialog_id;
|
|
||||||
for (auto &full_info : full_infos) {
|
for (auto &full_info : full_infos) {
|
||||||
file_stats.add(std::move(full_info));
|
file_stats.add(std::move(full_info));
|
||||||
if (token_) {
|
if (token_) {
|
||||||
|
@ -13,35 +13,32 @@
|
|||||||
|
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
|
||||||
void *TdCClientCreate() {
|
static td::ClientManager *GetClientManager() {
|
||||||
return new td::Client();
|
return td::ClientManager::get_manager_singleton();
|
||||||
}
|
}
|
||||||
|
|
||||||
void TdCClientSend(void *instance, struct TdRequest request) {
|
int TdCClientCreateId() {
|
||||||
auto client = static_cast<td::Client *>(instance);
|
return GetClientManager()->create_client_id();
|
||||||
td::Client::Request client_request;
|
}
|
||||||
client_request.id = request.id;
|
|
||||||
client_request.function = TdConvertToInternal(request.function);
|
void TdCClientSend(int client_id, struct TdRequest request) {
|
||||||
|
GetClientManager()->send(client_id, request.request_id, TdConvertToInternal(request.function));
|
||||||
TdDestroyObjectFunction(request.function);
|
TdDestroyObjectFunction(request.function);
|
||||||
client->send(std::move(client_request));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TdResponse TdCClientReceive(void *instance, double timeout) {
|
TdResponse TdCClientReceive(double timeout) {
|
||||||
auto client = static_cast<td::Client *>(instance);
|
auto response = GetClientManager()->receive(timeout);
|
||||||
auto response = client->receive(timeout);
|
|
||||||
TdResponse c_response;
|
TdResponse c_response;
|
||||||
c_response.id = response.id;
|
c_response.client_id = response.client_id;
|
||||||
|
c_response.request_id = response.request_id;
|
||||||
c_response.object = response.object == nullptr ? nullptr : TdConvertFromInternal(*response.object);
|
c_response.object = response.object == nullptr ? nullptr : TdConvertFromInternal(*response.object);
|
||||||
return c_response;
|
return c_response;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TdCClientDestroy(void *instance) {
|
TdObject *TdCClientExecute(TdFunction *function) {
|
||||||
auto client = static_cast<td::Client *>(instance);
|
auto result = td::ClientManager::execute(TdConvertToInternal(function));
|
||||||
delete client;
|
TdDestroyObjectFunction(function);
|
||||||
}
|
return TdConvertFromInternal(*result);
|
||||||
|
|
||||||
void TdCClientSetVerbosity(int new_verbosity_level) {
|
|
||||||
td::Log::set_verbosity_level(new_verbosity_level);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TdVectorInt *TdCreateObjectVectorInt(int size, int *data) {
|
TdVectorInt *TdCreateObjectVectorInt(int size, int *data) {
|
||||||
|
@ -18,21 +18,23 @@ struct TdVectorObject *TdCreateObjectVectorObject(int size, struct TdObject **da
|
|||||||
struct TdBytes TdCreateObjectBytes(unsigned char *data, int len);
|
struct TdBytes TdCreateObjectBytes(unsigned char *data, int len);
|
||||||
|
|
||||||
struct TdRequest {
|
struct TdRequest {
|
||||||
long long id;
|
long long request_id;
|
||||||
TdFunction *function;
|
TdFunction *function;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct TdResponse {
|
struct TdResponse {
|
||||||
long long id;
|
long long request_id;
|
||||||
|
int client_id;
|
||||||
TdObject *object;
|
TdObject *object;
|
||||||
};
|
};
|
||||||
|
|
||||||
void *TdCClientCreate();
|
int TdCClientCreateId();
|
||||||
void TdCClientSend(void *instance, struct TdRequest cmd);
|
|
||||||
struct TdResponse TdCClientSendCommandSync(void *instance, double timeout);
|
|
||||||
void TdCClientDestroy(void *instance);
|
|
||||||
|
|
||||||
void TdCClientSetVerbosity(int new_verbosity_level);
|
void TdCClientSend(int client_id, struct TdRequest request);
|
||||||
|
|
||||||
|
TdResponse TdCClientReceive(double timeout);
|
||||||
|
|
||||||
|
TdObject *TdCClientExecute(TdFunction *function);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
@ -6,6 +6,7 @@
|
|||||||
//
|
//
|
||||||
#include "td/db/SqliteKeyValue.h"
|
#include "td/db/SqliteKeyValue.h"
|
||||||
|
|
||||||
|
#include "td/utils/base64.h"
|
||||||
#include "td/utils/logging.h"
|
#include "td/utils/logging.h"
|
||||||
#include "td/utils/ScopeGuard.h"
|
#include "td/utils/ScopeGuard.h"
|
||||||
|
|
||||||
@ -54,7 +55,7 @@ SqliteKeyValue::SeqNo SqliteKeyValue::set(Slice key, Slice value) {
|
|||||||
set_stmt_.bind_blob(2, value).ensure();
|
set_stmt_.bind_blob(2, value).ensure();
|
||||||
auto status = set_stmt_.step();
|
auto status = set_stmt_.step();
|
||||||
if (status.is_error()) {
|
if (status.is_error()) {
|
||||||
LOG(FATAL) << "Failed to set \"" << key << "\": " << status.error();
|
LOG(FATAL) << "Failed to set \"" << base64_encode(key) << "\": " << status.error();
|
||||||
}
|
}
|
||||||
// set_stmt_.step().ensure();
|
// set_stmt_.step().ensure();
|
||||||
set_stmt_.reset();
|
set_stmt_.reset();
|
||||||
|
Loading…
Reference in New Issue
Block a user