Move some methods to DialogActionManager.
This commit is contained in:
parent
4bc9f8d72e
commit
b684039566
@ -6,13 +6,389 @@
|
||||
//
|
||||
#include "td/telegram/DialogActionManager.h"
|
||||
|
||||
#include "td/telegram/AuthManager.h"
|
||||
#include "td/telegram/ContactsManager.h"
|
||||
#include "td/telegram/DialogManager.h"
|
||||
#include "td/telegram/Global.h"
|
||||
#include "td/telegram/MessageContent.h"
|
||||
#include "td/telegram/MessageSender.h"
|
||||
#include "td/telegram/MessagesManager.h"
|
||||
#include "td/telegram/net/NetQuery.h"
|
||||
#include "td/telegram/SecretChatsManager.h"
|
||||
#include "td/telegram/Td.h"
|
||||
#include "td/telegram/telegram_api.h"
|
||||
|
||||
#include "td/utils/buffer.h"
|
||||
#include "td/utils/logging.h"
|
||||
#include "td/utils/Time.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
namespace td {
|
||||
|
||||
class SetTypingQuery final : public Td::ResultHandler {
|
||||
Promise<Unit> promise_;
|
||||
DialogId dialog_id_;
|
||||
int32 generation_ = 0;
|
||||
|
||||
public:
|
||||
explicit SetTypingQuery(Promise<Unit> &&promise) : promise_(std::move(promise)) {
|
||||
}
|
||||
|
||||
NetQueryRef send(DialogId dialog_id, tl_object_ptr<telegram_api::InputPeer> &&input_peer,
|
||||
MessageId top_thread_message_id, tl_object_ptr<telegram_api::SendMessageAction> &&action) {
|
||||
dialog_id_ = dialog_id;
|
||||
CHECK(input_peer != nullptr);
|
||||
|
||||
int32 flags = 0;
|
||||
if (top_thread_message_id.is_valid()) {
|
||||
flags |= telegram_api::messages_setTyping::TOP_MSG_ID_MASK;
|
||||
}
|
||||
auto query = G()->net_query_creator().create(telegram_api::messages_setTyping(
|
||||
flags, std::move(input_peer), top_thread_message_id.get_server_message_id().get(), std::move(action)));
|
||||
query->total_timeout_limit_ = 2;
|
||||
auto result = query.get_weak();
|
||||
generation_ = result.generation();
|
||||
send_query(std::move(query));
|
||||
return result;
|
||||
}
|
||||
|
||||
void on_result(BufferSlice packet) final {
|
||||
auto result_ptr = fetch_result<telegram_api::messages_setTyping>(packet);
|
||||
if (result_ptr.is_error()) {
|
||||
return on_error(result_ptr.move_as_error());
|
||||
}
|
||||
|
||||
// ignore result
|
||||
promise_.set_value(Unit());
|
||||
|
||||
send_closure_later(G()->dialog_action_manager(), &DialogActionManager::after_set_typing_query, dialog_id_,
|
||||
generation_);
|
||||
}
|
||||
|
||||
void on_error(Status status) final {
|
||||
if (status.code() == NetQuery::Canceled) {
|
||||
return promise_.set_value(Unit());
|
||||
}
|
||||
|
||||
if (!td_->dialog_manager_->on_get_dialog_error(dialog_id_, status, "SetTypingQuery")) {
|
||||
LOG(INFO) << "Receive error for set typing: " << status;
|
||||
}
|
||||
promise_.set_error(std::move(status));
|
||||
|
||||
send_closure_later(G()->dialog_action_manager(), &DialogActionManager::after_set_typing_query, dialog_id_,
|
||||
generation_);
|
||||
}
|
||||
};
|
||||
|
||||
DialogActionManager::DialogActionManager(Td *td, ActorShared<> parent) : td_(td), parent_(std::move(parent)) {
|
||||
active_dialog_action_timeout_.set_callback(on_active_dialog_action_timeout_callback);
|
||||
active_dialog_action_timeout_.set_callback_data(static_cast<void *>(this));
|
||||
}
|
||||
|
||||
void DialogActionManager::tear_down() {
|
||||
parent_.reset();
|
||||
}
|
||||
|
||||
void DialogActionManager::on_active_dialog_action_timeout_callback(void *dialog_action_manager_ptr,
|
||||
int64 dialog_id_int) {
|
||||
if (G()->close_flag()) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto dialog_action_manager = static_cast<DialogActionManager *>(dialog_action_manager_ptr);
|
||||
send_closure_later(dialog_action_manager->actor_id(dialog_action_manager),
|
||||
&DialogActionManager::on_active_dialog_action_timeout, DialogId(dialog_id_int));
|
||||
}
|
||||
|
||||
void DialogActionManager::on_dialog_action(DialogId dialog_id, MessageId top_thread_message_id,
|
||||
DialogId typing_dialog_id, DialogAction action, int32 date,
|
||||
MessageContentType message_content_type) {
|
||||
if (td_->auth_manager_->is_bot() || !typing_dialog_id.is_valid()) {
|
||||
return;
|
||||
}
|
||||
if (top_thread_message_id != MessageId() && !top_thread_message_id.is_valid()) {
|
||||
LOG(ERROR) << "Ignore " << action << " in the message thread of " << top_thread_message_id;
|
||||
return;
|
||||
}
|
||||
|
||||
auto dialog_type = dialog_id.get_type();
|
||||
if (action == DialogAction::get_speaking_action()) {
|
||||
if ((dialog_type != DialogType::Chat && dialog_type != DialogType::Channel) || top_thread_message_id.is_valid()) {
|
||||
LOG(ERROR) << "Receive " << action << " in thread of " << top_thread_message_id << " in " << dialog_id;
|
||||
return;
|
||||
}
|
||||
return td_->messages_manager_->on_dialog_speaking_action(dialog_id, typing_dialog_id, date);
|
||||
}
|
||||
|
||||
if (td_->dialog_manager_->is_broadcast_channel(dialog_id)) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto typing_dialog_type = typing_dialog_id.get_type();
|
||||
if (typing_dialog_type != DialogType::User && dialog_type != DialogType::Chat && dialog_type != DialogType::Channel) {
|
||||
LOG(ERROR) << "Ignore " << action << " of " << typing_dialog_id << " in " << dialog_id;
|
||||
return;
|
||||
}
|
||||
|
||||
{
|
||||
auto message_import_progress = action.get_importing_messages_action_progress();
|
||||
if (message_import_progress >= 0) {
|
||||
// TODO
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
auto clicking_info = action.get_clicking_animated_emoji_action_info();
|
||||
if (!clicking_info.data.empty()) {
|
||||
if (date > G()->unix_time() - 10 && dialog_type == DialogType::User && dialog_id == typing_dialog_id) {
|
||||
td_->messages_manager_->on_message_animated_emoji_clicked(
|
||||
{dialog_id, MessageId(ServerMessageId(clicking_info.message_id))}, std::move(clicking_info.emoji),
|
||||
std::move(clicking_info.data));
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (is_unsent_animated_emoji_click(td_, dialog_id, action)) {
|
||||
LOG(DEBUG) << "Ignore unsent " << action;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!td_->messages_manager_->have_dialog(dialog_id)) {
|
||||
LOG(DEBUG) << "Ignore " << action << " in unknown " << dialog_id;
|
||||
return;
|
||||
}
|
||||
|
||||
if (typing_dialog_type == DialogType::User) {
|
||||
if (!td_->contacts_manager_->have_min_user(typing_dialog_id.get_user_id())) {
|
||||
LOG(DEBUG) << "Ignore " << action << " of unknown " << typing_dialog_id.get_user_id();
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
if (!td_->dialog_manager_->have_dialog_info_force(typing_dialog_id, "on_dialog_action")) {
|
||||
LOG(DEBUG) << "Ignore " << action << " of unknown " << typing_dialog_id;
|
||||
return;
|
||||
}
|
||||
td_->dialog_manager_->force_create_dialog(typing_dialog_id, "on_dialog_action", true);
|
||||
if (!td_->messages_manager_->have_dialog(typing_dialog_id)) {
|
||||
LOG(ERROR) << "Failed to create typing " << typing_dialog_id;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
bool is_canceled = action == DialogAction();
|
||||
if ((!is_canceled || message_content_type != MessageContentType::None) && typing_dialog_type == DialogType::User) {
|
||||
td_->contacts_manager_->on_update_user_local_was_online(typing_dialog_id.get_user_id(), date);
|
||||
}
|
||||
|
||||
if (dialog_type == DialogType::User || dialog_type == DialogType::SecretChat) {
|
||||
CHECK(typing_dialog_type == DialogType::User);
|
||||
auto user_id = typing_dialog_id.get_user_id();
|
||||
if (!td_->contacts_manager_->is_user_bot(user_id) && !td_->contacts_manager_->is_user_status_exact(user_id) &&
|
||||
!td_->messages_manager_->is_dialog_opened(dialog_id) && !is_canceled) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (is_canceled) {
|
||||
// passed top_thread_message_id must be ignored
|
||||
auto actions_it = active_dialog_actions_.find(dialog_id);
|
||||
if (actions_it == active_dialog_actions_.end()) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto &active_actions = actions_it->second;
|
||||
auto it = std::find_if(
|
||||
active_actions.begin(), active_actions.end(),
|
||||
[typing_dialog_id](const ActiveDialogAction &action) { return action.typing_dialog_id == typing_dialog_id; });
|
||||
if (it == active_actions.end()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!(typing_dialog_type == DialogType::User &&
|
||||
td_->contacts_manager_->is_user_bot(typing_dialog_id.get_user_id())) &&
|
||||
!it->action.is_canceled_by_message_of_type(message_content_type)) {
|
||||
return;
|
||||
}
|
||||
|
||||
LOG(DEBUG) << "Cancel action of " << typing_dialog_id << " in " << dialog_id;
|
||||
top_thread_message_id = it->top_thread_message_id;
|
||||
active_actions.erase(it);
|
||||
if (active_actions.empty()) {
|
||||
active_dialog_actions_.erase(dialog_id);
|
||||
LOG(DEBUG) << "Cancel action timeout in " << dialog_id;
|
||||
active_dialog_action_timeout_.cancel_timeout(dialog_id.get());
|
||||
}
|
||||
} else {
|
||||
if (date < G()->unix_time() - DIALOG_ACTION_TIMEOUT - 60) {
|
||||
LOG(DEBUG) << "Ignore too old action of " << typing_dialog_id << " in " << dialog_id << " sent at " << date;
|
||||
return;
|
||||
}
|
||||
auto &active_actions = active_dialog_actions_[dialog_id];
|
||||
auto it = std::find_if(
|
||||
active_actions.begin(), active_actions.end(),
|
||||
[typing_dialog_id](const ActiveDialogAction &action) { return action.typing_dialog_id == typing_dialog_id; });
|
||||
MessageId prev_top_thread_message_id;
|
||||
DialogAction prev_action;
|
||||
if (it != active_actions.end()) {
|
||||
LOG(DEBUG) << "Re-add action of " << typing_dialog_id << " in " << dialog_id;
|
||||
prev_top_thread_message_id = it->top_thread_message_id;
|
||||
prev_action = it->action;
|
||||
active_actions.erase(it);
|
||||
} else {
|
||||
LOG(DEBUG) << "Add action of " << typing_dialog_id << " in " << dialog_id;
|
||||
}
|
||||
|
||||
active_actions.emplace_back(top_thread_message_id, typing_dialog_id, action, Time::now());
|
||||
if (top_thread_message_id == prev_top_thread_message_id && action == prev_action) {
|
||||
return;
|
||||
}
|
||||
if (top_thread_message_id != prev_top_thread_message_id && prev_top_thread_message_id.is_valid()) {
|
||||
send_update_chat_action(dialog_id, prev_top_thread_message_id, typing_dialog_id, DialogAction());
|
||||
}
|
||||
if (active_actions.size() == 1u) {
|
||||
LOG(DEBUG) << "Set action timeout in " << dialog_id;
|
||||
active_dialog_action_timeout_.set_timeout_in(dialog_id.get(), DIALOG_ACTION_TIMEOUT);
|
||||
}
|
||||
}
|
||||
|
||||
if (top_thread_message_id.is_valid()) {
|
||||
send_update_chat_action(dialog_id, MessageId(), typing_dialog_id, action);
|
||||
}
|
||||
send_update_chat_action(dialog_id, top_thread_message_id, typing_dialog_id, action);
|
||||
}
|
||||
|
||||
void DialogActionManager::send_update_chat_action(DialogId dialog_id, MessageId top_thread_message_id,
|
||||
DialogId typing_dialog_id, const DialogAction &action) {
|
||||
if (td_->auth_manager_->is_bot()) {
|
||||
return;
|
||||
}
|
||||
|
||||
LOG(DEBUG) << "Send " << action << " of " << typing_dialog_id << " in thread of " << top_thread_message_id << " in "
|
||||
<< dialog_id;
|
||||
send_closure(G()->td(), &Td::send_update,
|
||||
td_api::make_object<td_api::updateChatAction>(
|
||||
td_->dialog_manager_->get_chat_id_object(dialog_id, "updateChatAction"), top_thread_message_id.get(),
|
||||
get_message_sender_object(td_, typing_dialog_id, "send_update_chat_action"),
|
||||
action.get_chat_action_object()));
|
||||
}
|
||||
|
||||
void DialogActionManager::send_dialog_action(DialogId dialog_id, MessageId top_thread_message_id, DialogAction action,
|
||||
Promise<Unit> &&promise) {
|
||||
if (!td_->dialog_manager_->have_dialog_force(dialog_id, "send_dialog_action")) {
|
||||
return promise.set_error(Status::Error(400, "Chat not found"));
|
||||
}
|
||||
if (top_thread_message_id != MessageId() &&
|
||||
(!top_thread_message_id.is_valid() || !top_thread_message_id.is_server())) {
|
||||
return promise.set_error(Status::Error(400, "Invalid message thread specified"));
|
||||
}
|
||||
|
||||
if (td_->dialog_manager_->is_forum_channel(dialog_id) && !top_thread_message_id.is_valid()) {
|
||||
top_thread_message_id = MessageId(ServerMessageId(1));
|
||||
}
|
||||
|
||||
tl_object_ptr<telegram_api::InputPeer> input_peer;
|
||||
if (action == DialogAction::get_speaking_action()) {
|
||||
input_peer = td_->dialog_manager_->get_input_peer(dialog_id, AccessRights::Read);
|
||||
if (input_peer == nullptr) {
|
||||
return promise.set_error(Status::Error(400, "Have no access to the chat"));
|
||||
}
|
||||
} else {
|
||||
if (!td_->dialog_manager_->have_input_peer(dialog_id, AccessRights::Write)) {
|
||||
if (td_->auth_manager_->is_bot()) {
|
||||
return promise.set_error(Status::Error(400, "Have no write access to the chat"));
|
||||
}
|
||||
return promise.set_value(Unit());
|
||||
}
|
||||
|
||||
if (td_->dialog_manager_->is_dialog_action_unneeded(dialog_id)) {
|
||||
LOG(INFO) << "Skip unneeded " << action << " in " << dialog_id;
|
||||
return promise.set_value(Unit());
|
||||
}
|
||||
|
||||
input_peer = td_->dialog_manager_->get_input_peer(dialog_id, AccessRights::Write);
|
||||
CHECK(input_peer != nullptr);
|
||||
}
|
||||
|
||||
if (dialog_id.get_type() == DialogType::SecretChat) {
|
||||
send_closure(G()->secret_chats_manager(), &SecretChatsManager::send_message_action, dialog_id.get_secret_chat_id(),
|
||||
action.get_secret_input_send_message_action());
|
||||
promise.set_value(Unit());
|
||||
return;
|
||||
}
|
||||
|
||||
auto new_query_ref =
|
||||
td_->create_handler<SetTypingQuery>(std::move(promise))
|
||||
->send(dialog_id, std::move(input_peer), top_thread_message_id, action.get_input_send_message_action());
|
||||
if (td_->auth_manager_->is_bot()) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto &query_ref = set_typing_query_[dialog_id];
|
||||
if (!query_ref.empty()) {
|
||||
LOG(INFO) << "Cancel previous send chat action query";
|
||||
cancel_query(query_ref);
|
||||
}
|
||||
query_ref = std::move(new_query_ref);
|
||||
}
|
||||
|
||||
void DialogActionManager::cancel_send_dialog_action_queries(DialogId dialog_id) {
|
||||
auto it = set_typing_query_.find(dialog_id);
|
||||
if (it == set_typing_query_.end()) {
|
||||
return;
|
||||
}
|
||||
if (!it->second.empty()) {
|
||||
cancel_query(it->second);
|
||||
}
|
||||
set_typing_query_.erase(it);
|
||||
}
|
||||
|
||||
void DialogActionManager::after_set_typing_query(DialogId dialog_id, int32 generation) {
|
||||
auto it = set_typing_query_.find(dialog_id);
|
||||
if (it != set_typing_query_.end() && (!it->second.is_alive() || it->second.generation() == generation)) {
|
||||
set_typing_query_.erase(it);
|
||||
}
|
||||
}
|
||||
|
||||
void DialogActionManager::on_active_dialog_action_timeout(DialogId dialog_id) {
|
||||
LOG(DEBUG) << "Receive active dialog action timeout in " << dialog_id;
|
||||
auto actions_it = active_dialog_actions_.find(dialog_id);
|
||||
if (actions_it == active_dialog_actions_.end()) {
|
||||
return;
|
||||
}
|
||||
CHECK(!actions_it->second.empty());
|
||||
|
||||
auto now = Time::now();
|
||||
DialogId prev_typing_dialog_id;
|
||||
while (actions_it->second[0].start_time + DIALOG_ACTION_TIMEOUT < now + 0.1) {
|
||||
CHECK(actions_it->second[0].typing_dialog_id != prev_typing_dialog_id);
|
||||
prev_typing_dialog_id = actions_it->second[0].typing_dialog_id;
|
||||
on_dialog_action(dialog_id, actions_it->second[0].top_thread_message_id, actions_it->second[0].typing_dialog_id,
|
||||
DialogAction(), 0);
|
||||
|
||||
actions_it = active_dialog_actions_.find(dialog_id);
|
||||
if (actions_it == active_dialog_actions_.end()) {
|
||||
return;
|
||||
}
|
||||
CHECK(!actions_it->second.empty());
|
||||
}
|
||||
|
||||
LOG(DEBUG) << "Schedule next action timeout in " << dialog_id;
|
||||
active_dialog_action_timeout_.add_timeout_in(dialog_id.get(),
|
||||
actions_it->second[0].start_time + DIALOG_ACTION_TIMEOUT - now);
|
||||
}
|
||||
|
||||
void DialogActionManager::clear_active_dialog_actions(DialogId dialog_id) {
|
||||
LOG(DEBUG) << "Clear active dialog actions in " << dialog_id;
|
||||
auto actions_it = active_dialog_actions_.find(dialog_id);
|
||||
while (actions_it != active_dialog_actions_.end()) {
|
||||
CHECK(!actions_it->second.empty());
|
||||
on_dialog_action(dialog_id, actions_it->second[0].top_thread_message_id, actions_it->second[0].typing_dialog_id,
|
||||
DialogAction(), 0);
|
||||
actions_it = active_dialog_actions_.find(dialog_id);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace td
|
||||
|
@ -6,9 +6,18 @@
|
||||
//
|
||||
#pragma once
|
||||
|
||||
#include "td/telegram/DialogAction.h"
|
||||
#include "td/telegram/DialogId.h"
|
||||
#include "td/telegram/MessageContentType.h"
|
||||
#include "td/telegram/MessageId.h"
|
||||
#include "td/telegram/net/NetQuery.h"
|
||||
#include "td/telegram/td_api.h"
|
||||
|
||||
#include "td/actor/actor.h"
|
||||
#include "td/actor/MultiTimeout.h"
|
||||
|
||||
#include "td/utils/common.h"
|
||||
#include "td/utils/FlatHashMap.h"
|
||||
|
||||
namespace td {
|
||||
|
||||
@ -18,9 +27,51 @@ class DialogActionManager final : public Actor {
|
||||
public:
|
||||
DialogActionManager(Td *td, ActorShared<> parent);
|
||||
|
||||
void on_dialog_action(DialogId dialog_id, MessageId top_thread_message_id, DialogId typing_dialog_id,
|
||||
DialogAction action, int32 date,
|
||||
MessageContentType message_content_type = MessageContentType::None);
|
||||
|
||||
void send_dialog_action(DialogId dialog_id, MessageId top_thread_message_id, DialogAction action,
|
||||
Promise<Unit> &&promise);
|
||||
|
||||
void cancel_send_dialog_action_queries(DialogId dialog_id);
|
||||
|
||||
void after_set_typing_query(DialogId dialog_id, int32 generation);
|
||||
|
||||
void clear_active_dialog_actions(DialogId dialog_id);
|
||||
|
||||
private:
|
||||
static constexpr double DIALOG_ACTION_TIMEOUT = 5.5;
|
||||
|
||||
void tear_down() final;
|
||||
|
||||
void send_update_chat_action(DialogId dialog_id, MessageId top_thread_message_id, DialogId typing_dialog_id,
|
||||
const DialogAction &action);
|
||||
|
||||
static void on_active_dialog_action_timeout_callback(void *dialog_action_manager_ptr, int64 dialog_id_int);
|
||||
|
||||
void on_active_dialog_action_timeout(DialogId dialog_id);
|
||||
|
||||
struct ActiveDialogAction {
|
||||
MessageId top_thread_message_id;
|
||||
DialogId typing_dialog_id;
|
||||
DialogAction action;
|
||||
double start_time;
|
||||
|
||||
ActiveDialogAction(MessageId top_thread_message_id, DialogId typing_dialog_id, DialogAction action,
|
||||
double start_time)
|
||||
: top_thread_message_id(top_thread_message_id)
|
||||
, typing_dialog_id(typing_dialog_id)
|
||||
, action(std::move(action))
|
||||
, start_time(start_time) {
|
||||
}
|
||||
};
|
||||
FlatHashMap<DialogId, std::vector<ActiveDialogAction>, DialogIdHash> active_dialog_actions_;
|
||||
|
||||
MultiTimeout active_dialog_action_timeout_{"ActiveDialogActionTimeout"};
|
||||
|
||||
FlatHashMap<DialogId, NetQueryRef, DialogIdHash> set_typing_query_;
|
||||
|
||||
Td *td_;
|
||||
ActorShared<> parent_;
|
||||
};
|
||||
|
@ -41,6 +41,7 @@ class CallManager;
|
||||
class ConfigManager;
|
||||
class ConnectionCreator;
|
||||
class ContactsManager;
|
||||
class DialogActionManager;
|
||||
class DialogFilterManager;
|
||||
class DialogManager;
|
||||
class DownloadManager;
|
||||
@ -246,6 +247,13 @@ class Global final : public ActorContext {
|
||||
contacts_manager_ = contacts_manager;
|
||||
}
|
||||
|
||||
ActorId<DialogActionManager> dialog_action_manager() const {
|
||||
return dialog_action_manager_;
|
||||
}
|
||||
void set_dialog_action_manager(ActorId<DialogActionManager> dialog_action_manager) {
|
||||
dialog_action_manager_ = std::move(dialog_action_manager);
|
||||
}
|
||||
|
||||
ActorId<DialogFilterManager> dialog_filter_manager() const {
|
||||
return dialog_filter_manager_;
|
||||
}
|
||||
@ -562,6 +570,7 @@ class Global final : public ActorContext {
|
||||
ActorId<CallManager> call_manager_;
|
||||
ActorId<ConfigManager> config_manager_;
|
||||
ActorId<ContactsManager> contacts_manager_;
|
||||
ActorId<DialogActionManager> dialog_action_manager_;
|
||||
ActorId<DialogFilterManager> dialog_filter_manager_;
|
||||
ActorId<DialogManager> dialog_manager_;
|
||||
ActorId<DownloadManager> download_manager_;
|
||||
|
@ -10,6 +10,7 @@
|
||||
#include "td/telegram/AuthManager.h"
|
||||
#include "td/telegram/ContactsManager.h"
|
||||
#include "td/telegram/DialogAction.h"
|
||||
#include "td/telegram/DialogActionManager.h"
|
||||
#include "td/telegram/DialogManager.h"
|
||||
#include "td/telegram/DialogParticipantFilter.h"
|
||||
#include "td/telegram/Global.h"
|
||||
@ -1099,8 +1100,8 @@ void GroupCallManager::on_send_speaking_action_timeout(GroupCallId group_call_id
|
||||
|
||||
pending_send_speaking_action_timeout_.add_timeout_in(group_call_id.get(), 4.0);
|
||||
|
||||
td_->messages_manager_->send_dialog_action(group_call->dialog_id, MessageId(), DialogAction::get_speaking_action(),
|
||||
Promise<Unit>());
|
||||
td_->dialog_action_manager_->send_dialog_action(group_call->dialog_id, MessageId(),
|
||||
DialogAction::get_speaking_action(), Promise<Unit>());
|
||||
}
|
||||
|
||||
void GroupCallManager::on_recent_speaker_update_timeout_callback(void *group_call_manager_ptr,
|
||||
|
@ -16,7 +16,9 @@
|
||||
#include "td/telegram/ChatReactions.hpp"
|
||||
#include "td/telegram/ContactsManager.h"
|
||||
#include "td/telegram/Dependencies.h"
|
||||
#include "td/telegram/DialogAction.h"
|
||||
#include "td/telegram/DialogActionBar.h"
|
||||
#include "td/telegram/DialogActionManager.h"
|
||||
#include "td/telegram/DialogDb.h"
|
||||
#include "td/telegram/DialogFilter.h"
|
||||
#include "td/telegram/DialogFilterManager.h"
|
||||
@ -52,7 +54,6 @@
|
||||
#include "td/telegram/MessageSender.h"
|
||||
#include "td/telegram/misc.h"
|
||||
#include "td/telegram/net/DcId.h"
|
||||
#include "td/telegram/net/NetQuery.h"
|
||||
#include "td/telegram/NotificationGroupInfo.hpp"
|
||||
#include "td/telegram/NotificationGroupType.h"
|
||||
#include "td/telegram/NotificationManager.h"
|
||||
@ -3561,59 +3562,6 @@ class SendBotRequestedPeerQuery final : public Td::ResultHandler {
|
||||
}
|
||||
};
|
||||
|
||||
class SetTypingQuery final : public Td::ResultHandler {
|
||||
Promise<Unit> promise_;
|
||||
DialogId dialog_id_;
|
||||
int32 generation_ = 0;
|
||||
|
||||
public:
|
||||
explicit SetTypingQuery(Promise<Unit> &&promise) : promise_(std::move(promise)) {
|
||||
}
|
||||
|
||||
NetQueryRef send(DialogId dialog_id, tl_object_ptr<telegram_api::InputPeer> &&input_peer,
|
||||
MessageId top_thread_message_id, tl_object_ptr<telegram_api::SendMessageAction> &&action) {
|
||||
dialog_id_ = dialog_id;
|
||||
CHECK(input_peer != nullptr);
|
||||
|
||||
int32 flags = 0;
|
||||
if (top_thread_message_id.is_valid()) {
|
||||
flags |= telegram_api::messages_setTyping::TOP_MSG_ID_MASK;
|
||||
}
|
||||
auto query = G()->net_query_creator().create(telegram_api::messages_setTyping(
|
||||
flags, std::move(input_peer), top_thread_message_id.get_server_message_id().get(), std::move(action)));
|
||||
query->total_timeout_limit_ = 2;
|
||||
auto result = query.get_weak();
|
||||
generation_ = result.generation();
|
||||
send_query(std::move(query));
|
||||
return result;
|
||||
}
|
||||
|
||||
void on_result(BufferSlice packet) final {
|
||||
auto result_ptr = fetch_result<telegram_api::messages_setTyping>(packet);
|
||||
if (result_ptr.is_error()) {
|
||||
return on_error(result_ptr.move_as_error());
|
||||
}
|
||||
|
||||
// ignore result
|
||||
promise_.set_value(Unit());
|
||||
|
||||
send_closure_later(G()->messages_manager(), &MessagesManager::after_set_typing_query, dialog_id_, generation_);
|
||||
}
|
||||
|
||||
void on_error(Status status) final {
|
||||
if (status.code() == NetQuery::Canceled) {
|
||||
return promise_.set_value(Unit());
|
||||
}
|
||||
|
||||
if (!td_->dialog_manager_->on_get_dialog_error(dialog_id_, status, "SetTypingQuery")) {
|
||||
LOG(INFO) << "Receive error for set typing: " << status;
|
||||
}
|
||||
promise_.set_error(std::move(status));
|
||||
|
||||
send_closure_later(G()->messages_manager(), &MessagesManager::after_set_typing_query, dialog_id_, generation_);
|
||||
}
|
||||
};
|
||||
|
||||
class DeleteMessagesQuery final : public Td::ResultHandler {
|
||||
Promise<Unit> promise_;
|
||||
DialogId dialog_id_;
|
||||
@ -5282,9 +5230,6 @@ MessagesManager::MessagesManager(Td *td, ActorShared<> parent)
|
||||
pending_send_dialog_action_timeout_.set_callback(on_pending_send_dialog_action_timeout_callback);
|
||||
pending_send_dialog_action_timeout_.set_callback_data(static_cast<void *>(this));
|
||||
|
||||
active_dialog_action_timeout_.set_callback(on_active_dialog_action_timeout_callback);
|
||||
active_dialog_action_timeout_.set_callback_data(static_cast<void *>(this));
|
||||
|
||||
preload_folder_dialog_list_timeout_.set_callback(on_preload_folder_dialog_list_timeout_callback);
|
||||
preload_folder_dialog_list_timeout_.set_callback_data(static_cast<void *>(this));
|
||||
|
||||
@ -5407,16 +5352,6 @@ void MessagesManager::on_pending_send_dialog_action_timeout_callback(void *messa
|
||||
DialogId(dialog_id_int));
|
||||
}
|
||||
|
||||
void MessagesManager::on_active_dialog_action_timeout_callback(void *messages_manager_ptr, int64 dialog_id_int) {
|
||||
if (G()->close_flag()) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto messages_manager = static_cast<MessagesManager *>(messages_manager_ptr);
|
||||
send_closure_later(messages_manager->actor_id(messages_manager), &MessagesManager::on_active_dialog_action_timeout,
|
||||
DialogId(dialog_id_int));
|
||||
}
|
||||
|
||||
void MessagesManager::on_preload_folder_dialog_list_timeout_callback(void *messages_manager_ptr, int64 folder_id_int) {
|
||||
if (G()->close_flag()) {
|
||||
return;
|
||||
@ -6740,170 +6675,20 @@ void MessagesManager::on_update_created_public_broadcasts(vector<ChannelId> chan
|
||||
created_public_broadcasts_ = std::move(channel_ids);
|
||||
}
|
||||
|
||||
void MessagesManager::on_dialog_action(DialogId dialog_id, MessageId top_thread_message_id, DialogId typing_dialog_id,
|
||||
DialogAction action, int32 date, MessageContentType message_content_type) {
|
||||
if (td_->auth_manager_->is_bot() || !typing_dialog_id.is_valid()) {
|
||||
return;
|
||||
void MessagesManager::on_dialog_speaking_action(DialogId dialog_id, DialogId speaking_dialog_id, int32 date) {
|
||||
const Dialog *d = get_dialog_force(dialog_id, "on_dialog_speaking_action");
|
||||
if (d != nullptr && d->active_group_call_id.is_valid()) {
|
||||
auto group_call_id = td_->group_call_manager_->get_group_call_id(d->active_group_call_id, dialog_id);
|
||||
td_->group_call_manager_->on_user_speaking_in_group_call(group_call_id, speaking_dialog_id, false, date);
|
||||
}
|
||||
if (top_thread_message_id != MessageId() && !top_thread_message_id.is_valid()) {
|
||||
LOG(ERROR) << "Ignore " << action << " in the message thread of " << top_thread_message_id;
|
||||
return;
|
||||
}
|
||||
|
||||
void MessagesManager::on_message_animated_emoji_clicked(MessageFullId message_full_id, string &&emoji, string &&data) {
|
||||
const auto *m = get_message_force(message_full_id, "on_message_animated_emoji_clicked");
|
||||
if (m != nullptr) {
|
||||
on_message_content_animated_emoji_clicked(m->content.get(), message_full_id, td_, std::move(emoji),
|
||||
std::move(data));
|
||||
}
|
||||
|
||||
auto dialog_type = dialog_id.get_type();
|
||||
if (action == DialogAction::get_speaking_action()) {
|
||||
if ((dialog_type != DialogType::Chat && dialog_type != DialogType::Channel) || top_thread_message_id.is_valid()) {
|
||||
LOG(ERROR) << "Receive " << action << " in thread of " << top_thread_message_id << " in " << dialog_id;
|
||||
return;
|
||||
}
|
||||
const Dialog *d = get_dialog_force(dialog_id, "on_dialog_action");
|
||||
if (d != nullptr && d->active_group_call_id.is_valid()) {
|
||||
auto group_call_id = td_->group_call_manager_->get_group_call_id(d->active_group_call_id, dialog_id);
|
||||
td_->group_call_manager_->on_user_speaking_in_group_call(group_call_id, typing_dialog_id, false, date);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (td_->dialog_manager_->is_broadcast_channel(dialog_id)) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto typing_dialog_type = typing_dialog_id.get_type();
|
||||
if (typing_dialog_type != DialogType::User && dialog_type != DialogType::Chat && dialog_type != DialogType::Channel) {
|
||||
LOG(ERROR) << "Ignore " << action << " of " << typing_dialog_id << " in " << dialog_id;
|
||||
return;
|
||||
}
|
||||
|
||||
{
|
||||
auto message_import_progress = action.get_importing_messages_action_progress();
|
||||
if (message_import_progress >= 0) {
|
||||
// TODO
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
auto clicking_info = action.get_clicking_animated_emoji_action_info();
|
||||
if (!clicking_info.data.empty()) {
|
||||
if (date > G()->unix_time() - 10 && dialog_type == DialogType::User && dialog_id == typing_dialog_id) {
|
||||
MessageFullId message_full_id{dialog_id, MessageId(ServerMessageId(clicking_info.message_id))};
|
||||
auto *m = get_message_force(message_full_id, "on_dialog_action");
|
||||
if (m != nullptr) {
|
||||
on_message_content_animated_emoji_clicked(m->content.get(), message_full_id, td_,
|
||||
std::move(clicking_info.emoji), std::move(clicking_info.data));
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (is_unsent_animated_emoji_click(td_, dialog_id, action)) {
|
||||
LOG(DEBUG) << "Ignore unsent " << action;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!have_dialog(dialog_id)) {
|
||||
LOG(DEBUG) << "Ignore " << action << " in unknown " << dialog_id;
|
||||
return;
|
||||
}
|
||||
|
||||
if (typing_dialog_type == DialogType::User) {
|
||||
if (!td_->contacts_manager_->have_min_user(typing_dialog_id.get_user_id())) {
|
||||
LOG(DEBUG) << "Ignore " << action << " of unknown " << typing_dialog_id.get_user_id();
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
if (!td_->dialog_manager_->have_dialog_info_force(typing_dialog_id, "on_dialog_action")) {
|
||||
LOG(DEBUG) << "Ignore " << action << " of unknown " << typing_dialog_id;
|
||||
return;
|
||||
}
|
||||
force_create_dialog(typing_dialog_id, "on_dialog_action", true);
|
||||
if (!have_dialog(typing_dialog_id)) {
|
||||
LOG(ERROR) << "Failed to create typing " << typing_dialog_id;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
bool is_canceled = action == DialogAction();
|
||||
if ((!is_canceled || message_content_type != MessageContentType::None) && typing_dialog_type == DialogType::User) {
|
||||
td_->contacts_manager_->on_update_user_local_was_online(typing_dialog_id.get_user_id(), date);
|
||||
}
|
||||
|
||||
if (dialog_type == DialogType::User || dialog_type == DialogType::SecretChat) {
|
||||
CHECK(typing_dialog_type == DialogType::User);
|
||||
auto user_id = typing_dialog_id.get_user_id();
|
||||
if (!td_->contacts_manager_->is_user_bot(user_id) && !td_->contacts_manager_->is_user_status_exact(user_id) &&
|
||||
!is_dialog_opened(dialog_id) && !is_canceled) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (is_canceled) {
|
||||
// passed top_thread_message_id must be ignored
|
||||
auto actions_it = active_dialog_actions_.find(dialog_id);
|
||||
if (actions_it == active_dialog_actions_.end()) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto &active_actions = actions_it->second;
|
||||
auto it = std::find_if(
|
||||
active_actions.begin(), active_actions.end(),
|
||||
[typing_dialog_id](const ActiveDialogAction &action) { return action.typing_dialog_id == typing_dialog_id; });
|
||||
if (it == active_actions.end()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!(typing_dialog_type == DialogType::User &&
|
||||
td_->contacts_manager_->is_user_bot(typing_dialog_id.get_user_id())) &&
|
||||
!it->action.is_canceled_by_message_of_type(message_content_type)) {
|
||||
return;
|
||||
}
|
||||
|
||||
LOG(DEBUG) << "Cancel action of " << typing_dialog_id << " in " << dialog_id;
|
||||
top_thread_message_id = it->top_thread_message_id;
|
||||
active_actions.erase(it);
|
||||
if (active_actions.empty()) {
|
||||
active_dialog_actions_.erase(dialog_id);
|
||||
LOG(DEBUG) << "Cancel action timeout in " << dialog_id;
|
||||
active_dialog_action_timeout_.cancel_timeout(dialog_id.get());
|
||||
}
|
||||
} else {
|
||||
if (date < G()->unix_time() - DIALOG_ACTION_TIMEOUT - 60) {
|
||||
LOG(DEBUG) << "Ignore too old action of " << typing_dialog_id << " in " << dialog_id << " sent at " << date;
|
||||
return;
|
||||
}
|
||||
auto &active_actions = active_dialog_actions_[dialog_id];
|
||||
auto it = std::find_if(
|
||||
active_actions.begin(), active_actions.end(),
|
||||
[typing_dialog_id](const ActiveDialogAction &action) { return action.typing_dialog_id == typing_dialog_id; });
|
||||
MessageId prev_top_thread_message_id;
|
||||
DialogAction prev_action;
|
||||
if (it != active_actions.end()) {
|
||||
LOG(DEBUG) << "Re-add action of " << typing_dialog_id << " in " << dialog_id;
|
||||
prev_top_thread_message_id = it->top_thread_message_id;
|
||||
prev_action = it->action;
|
||||
active_actions.erase(it);
|
||||
} else {
|
||||
LOG(DEBUG) << "Add action of " << typing_dialog_id << " in " << dialog_id;
|
||||
}
|
||||
|
||||
active_actions.emplace_back(top_thread_message_id, typing_dialog_id, action, Time::now());
|
||||
if (top_thread_message_id == prev_top_thread_message_id && action == prev_action) {
|
||||
return;
|
||||
}
|
||||
if (top_thread_message_id != prev_top_thread_message_id && prev_top_thread_message_id.is_valid()) {
|
||||
send_update_chat_action(dialog_id, prev_top_thread_message_id, typing_dialog_id, DialogAction());
|
||||
}
|
||||
if (active_actions.size() == 1u) {
|
||||
LOG(DEBUG) << "Set action timeout in " << dialog_id;
|
||||
active_dialog_action_timeout_.set_timeout_in(dialog_id.get(), DIALOG_ACTION_TIMEOUT);
|
||||
}
|
||||
}
|
||||
|
||||
if (top_thread_message_id.is_valid()) {
|
||||
send_update_chat_action(dialog_id, MessageId(), typing_dialog_id, action);
|
||||
}
|
||||
send_update_chat_action(dialog_id, top_thread_message_id, typing_dialog_id, action);
|
||||
}
|
||||
|
||||
void MessagesManager::cancel_dialog_action(DialogId dialog_id, const Message *m) {
|
||||
@ -6913,8 +6698,8 @@ void MessagesManager::cancel_dialog_action(DialogId dialog_id, const Message *m)
|
||||
return;
|
||||
}
|
||||
|
||||
on_dialog_action(dialog_id, MessageId() /*ignored*/, get_message_sender(m), DialogAction(), m->date,
|
||||
m->content->get_type());
|
||||
td_->dialog_action_manager_->on_dialog_action(dialog_id, MessageId() /*ignored*/, get_message_sender(m),
|
||||
DialogAction(), m->date, m->content->get_type());
|
||||
}
|
||||
|
||||
void MessagesManager::add_postponed_channel_update(DialogId dialog_id, tl_object_ptr<telegram_api::Update> &&update,
|
||||
@ -23460,15 +23245,7 @@ void MessagesManager::set_dialog_default_send_message_as_dialog_id(DialogId dial
|
||||
return promise.set_error(Status::Error(400, "Can't access specified message sender chat"));
|
||||
}
|
||||
|
||||
{
|
||||
auto it = set_typing_query_.find(dialog_id);
|
||||
if (it != set_typing_query_.end()) {
|
||||
if (!it->second.empty()) {
|
||||
cancel_query(it->second);
|
||||
}
|
||||
set_typing_query_.erase(it);
|
||||
}
|
||||
}
|
||||
td_->dialog_action_manager_->cancel_send_dialog_action_queries(dialog_id);
|
||||
|
||||
td_->create_handler<SaveDefaultSendAsQuery>(std::move(promise))->send(dialog_id, message_sender_dialog_id);
|
||||
|
||||
@ -29091,21 +28868,6 @@ void MessagesManager::send_update_chat_has_scheduled_messages(Dialog *d, bool fr
|
||||
get_chat_id_object(d->dialog_id, "updateChatHasScheduledMessages"), has_scheduled_messages));
|
||||
}
|
||||
|
||||
void MessagesManager::send_update_chat_action(DialogId dialog_id, MessageId top_thread_message_id,
|
||||
DialogId typing_dialog_id, const DialogAction &action) {
|
||||
if (td_->auth_manager_->is_bot()) {
|
||||
return;
|
||||
}
|
||||
|
||||
LOG(DEBUG) << "Send " << action << " of " << typing_dialog_id << " in thread of " << top_thread_message_id << " in "
|
||||
<< dialog_id;
|
||||
send_closure(G()->td(), &Td::send_update,
|
||||
td_api::make_object<td_api::updateChatAction>(
|
||||
get_chat_id_object(dialog_id, "updateChatAction"), top_thread_message_id.get(),
|
||||
get_message_sender_object(td_, typing_dialog_id, "send_update_chat_action"),
|
||||
action.get_chat_action_object()));
|
||||
}
|
||||
|
||||
void MessagesManager::on_send_message_get_quick_ack(int64 random_id) {
|
||||
auto it = being_sent_messages_.find(random_id);
|
||||
if (it == being_sent_messages_.end()) {
|
||||
@ -31388,72 +31150,6 @@ MessagesManager::NotificationInfo *MessagesManager::add_dialog_notification_info
|
||||
return d->notification_info.get();
|
||||
}
|
||||
|
||||
void MessagesManager::send_dialog_action(DialogId dialog_id, MessageId top_thread_message_id, DialogAction action,
|
||||
Promise<Unit> &&promise) {
|
||||
if (!have_dialog_force(dialog_id, "send_dialog_action")) {
|
||||
return promise.set_error(Status::Error(400, "Chat not found"));
|
||||
}
|
||||
if (top_thread_message_id != MessageId() &&
|
||||
(!top_thread_message_id.is_valid() || !top_thread_message_id.is_server())) {
|
||||
return promise.set_error(Status::Error(400, "Invalid message thread specified"));
|
||||
}
|
||||
|
||||
if (td_->dialog_manager_->is_forum_channel(dialog_id) && !top_thread_message_id.is_valid()) {
|
||||
top_thread_message_id = MessageId(ServerMessageId(1));
|
||||
}
|
||||
|
||||
tl_object_ptr<telegram_api::InputPeer> input_peer;
|
||||
if (action == DialogAction::get_speaking_action()) {
|
||||
input_peer = td_->dialog_manager_->get_input_peer(dialog_id, AccessRights::Read);
|
||||
if (input_peer == nullptr) {
|
||||
return promise.set_error(Status::Error(400, "Have no access to the chat"));
|
||||
}
|
||||
} else {
|
||||
auto can_send_status = can_send_message(dialog_id);
|
||||
if (can_send_status.is_error()) {
|
||||
if (td_->auth_manager_->is_bot()) {
|
||||
return promise.set_error(std::move(can_send_status));
|
||||
}
|
||||
return promise.set_value(Unit());
|
||||
}
|
||||
|
||||
if (td_->dialog_manager_->is_dialog_action_unneeded(dialog_id)) {
|
||||
LOG(INFO) << "Skip unneeded " << action << " in " << dialog_id;
|
||||
return promise.set_value(Unit());
|
||||
}
|
||||
|
||||
input_peer = td_->dialog_manager_->get_input_peer(dialog_id, AccessRights::Write);
|
||||
}
|
||||
|
||||
if (dialog_id.get_type() == DialogType::SecretChat) {
|
||||
send_closure(G()->secret_chats_manager(), &SecretChatsManager::send_message_action, dialog_id.get_secret_chat_id(),
|
||||
action.get_secret_input_send_message_action());
|
||||
promise.set_value(Unit());
|
||||
return;
|
||||
}
|
||||
|
||||
auto new_query_ref =
|
||||
td_->create_handler<SetTypingQuery>(std::move(promise))
|
||||
->send(dialog_id, std::move(input_peer), top_thread_message_id, action.get_input_send_message_action());
|
||||
if (td_->auth_manager_->is_bot()) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto &query_ref = set_typing_query_[dialog_id];
|
||||
if (!query_ref.empty()) {
|
||||
LOG(INFO) << "Cancel previous send chat action query";
|
||||
cancel_query(query_ref);
|
||||
}
|
||||
query_ref = std::move(new_query_ref);
|
||||
}
|
||||
|
||||
void MessagesManager::after_set_typing_query(DialogId dialog_id, int32 generation) {
|
||||
auto it = set_typing_query_.find(dialog_id);
|
||||
if (it != set_typing_query_.end() && (!it->second.is_alive() || it->second.generation() == generation)) {
|
||||
set_typing_query_.erase(it);
|
||||
}
|
||||
}
|
||||
|
||||
void MessagesManager::on_send_dialog_action_timeout(DialogId dialog_id) {
|
||||
LOG(INFO) << "Receive send_chat_action timeout in " << dialog_id;
|
||||
Dialog *d = get_dialog(dialog_id);
|
||||
@ -31509,46 +31205,8 @@ void MessagesManager::on_send_dialog_action_timeout(DialogId dialog_id) {
|
||||
return;
|
||||
}
|
||||
LOG(INFO) << "Send " << action << " in " << dialog_id;
|
||||
send_dialog_action(dialog_id, m->top_thread_message_id, std::move(action), Promise<Unit>());
|
||||
}
|
||||
|
||||
void MessagesManager::on_active_dialog_action_timeout(DialogId dialog_id) {
|
||||
LOG(DEBUG) << "Receive active dialog action timeout in " << dialog_id;
|
||||
auto actions_it = active_dialog_actions_.find(dialog_id);
|
||||
if (actions_it == active_dialog_actions_.end()) {
|
||||
return;
|
||||
}
|
||||
CHECK(!actions_it->second.empty());
|
||||
|
||||
auto now = Time::now();
|
||||
DialogId prev_typing_dialog_id;
|
||||
while (actions_it->second[0].start_time + DIALOG_ACTION_TIMEOUT < now + 0.1) {
|
||||
CHECK(actions_it->second[0].typing_dialog_id != prev_typing_dialog_id);
|
||||
prev_typing_dialog_id = actions_it->second[0].typing_dialog_id;
|
||||
on_dialog_action(dialog_id, actions_it->second[0].top_thread_message_id, actions_it->second[0].typing_dialog_id,
|
||||
DialogAction(), 0);
|
||||
|
||||
actions_it = active_dialog_actions_.find(dialog_id);
|
||||
if (actions_it == active_dialog_actions_.end()) {
|
||||
return;
|
||||
}
|
||||
CHECK(!actions_it->second.empty());
|
||||
}
|
||||
|
||||
LOG(DEBUG) << "Schedule next action timeout in " << dialog_id;
|
||||
active_dialog_action_timeout_.add_timeout_in(dialog_id.get(),
|
||||
actions_it->second[0].start_time + DIALOG_ACTION_TIMEOUT - now);
|
||||
}
|
||||
|
||||
void MessagesManager::clear_active_dialog_actions(DialogId dialog_id) {
|
||||
LOG(DEBUG) << "Clear active dialog actions in " << dialog_id;
|
||||
auto actions_it = active_dialog_actions_.find(dialog_id);
|
||||
while (actions_it != active_dialog_actions_.end()) {
|
||||
CHECK(!actions_it->second.empty());
|
||||
on_dialog_action(dialog_id, actions_it->second[0].top_thread_message_id, actions_it->second[0].typing_dialog_id,
|
||||
DialogAction(), 0);
|
||||
actions_it = active_dialog_actions_.find(dialog_id);
|
||||
}
|
||||
td_->dialog_action_manager_->send_dialog_action(dialog_id, m->top_thread_message_id, std::move(action),
|
||||
Promise<Unit>());
|
||||
}
|
||||
|
||||
void MessagesManager::get_dialog_filter_dialog_count(td_api::object_ptr<td_api::chatFolder> filter,
|
||||
@ -35520,7 +35178,7 @@ bool MessagesManager::set_dialog_order(Dialog *d, int64 new_order, bool need_sen
|
||||
if (dialog_type == DialogType::Channel && is_removed) {
|
||||
remove_all_dialog_notifications(d, false, source);
|
||||
remove_all_dialog_notifications(d, true, source);
|
||||
clear_active_dialog_actions(dialog_id);
|
||||
td_->dialog_action_manager_->clear_active_dialog_actions(dialog_id);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -10,7 +10,6 @@
|
||||
#include "td/telegram/BackgroundInfo.h"
|
||||
#include "td/telegram/ChannelId.h"
|
||||
#include "td/telegram/ChatReactions.h"
|
||||
#include "td/telegram/DialogAction.h"
|
||||
#include "td/telegram/DialogDate.h"
|
||||
#include "td/telegram/DialogDb.h"
|
||||
#include "td/telegram/DialogFilterDialogInfo.h"
|
||||
@ -342,9 +341,9 @@ class MessagesManager final : public Actor {
|
||||
|
||||
void on_update_created_public_broadcasts(vector<ChannelId> channel_ids);
|
||||
|
||||
void on_dialog_action(DialogId dialog_id, MessageId top_thread_message_id, DialogId typing_dialog_id,
|
||||
DialogAction action, int32 date,
|
||||
MessageContentType message_content_type = MessageContentType::None);
|
||||
void on_dialog_speaking_action(DialogId dialog_id, DialogId speaking_dialog_id, int32 date);
|
||||
|
||||
void on_message_animated_emoji_clicked(MessageFullId message_full_id, string &&emoji, string &&data);
|
||||
|
||||
void read_history_inbox(DialogId dialog_id, MessageId max_message_id, int32 unread_count, const char *source);
|
||||
|
||||
@ -491,11 +490,6 @@ class MessagesManager final : public Actor {
|
||||
td_api::object_ptr<td_api::MessageSchedulingState> &&scheduling_state,
|
||||
Promise<Unit> &&promise);
|
||||
|
||||
void send_dialog_action(DialogId dialog_id, MessageId top_thread_message_id, DialogAction action,
|
||||
Promise<Unit> &&promise);
|
||||
|
||||
void after_set_typing_query(DialogId dialog_id, int32 generation);
|
||||
|
||||
void get_dialog_filter_dialog_count(td_api::object_ptr<td_api::chatFolder> filter, Promise<int32> &&promise);
|
||||
|
||||
void add_dialog_list_for_dialog_filter(DialogFilterId dialog_filter_id);
|
||||
@ -1642,8 +1636,6 @@ class MessagesManager final : public Actor {
|
||||
|
||||
static constexpr int32 SCHEDULE_WHEN_ONLINE_DATE = 2147483646;
|
||||
|
||||
static constexpr double DIALOG_ACTION_TIMEOUT = 5.5;
|
||||
|
||||
static constexpr const char *DELETE_MESSAGE_USER_REQUEST_SOURCE = "user request";
|
||||
|
||||
static constexpr bool DROP_SEND_MESSAGE_UPDATES = false;
|
||||
@ -2403,9 +2395,6 @@ class MessagesManager final : public Actor {
|
||||
|
||||
void send_update_chat_has_scheduled_messages(Dialog *d, bool from_deletion);
|
||||
|
||||
void send_update_chat_action(DialogId dialog_id, MessageId top_thread_message_id, DialogId typing_dialog_id,
|
||||
const DialogAction &action);
|
||||
|
||||
void repair_dialog_action_bar(Dialog *d, const char *source);
|
||||
|
||||
void hide_dialog_action_bar(Dialog *d);
|
||||
@ -2601,10 +2590,6 @@ class MessagesManager final : public Actor {
|
||||
|
||||
void on_send_dialog_action_timeout(DialogId dialog_id);
|
||||
|
||||
void on_active_dialog_action_timeout(DialogId dialog_id);
|
||||
|
||||
void clear_active_dialog_actions(DialogId dialog_id);
|
||||
|
||||
void cancel_dialog_action(DialogId dialog_id, const Message *m);
|
||||
|
||||
Dialog *get_dialog_by_message_id(MessageId message_id);
|
||||
@ -2999,8 +2984,6 @@ class MessagesManager final : public Actor {
|
||||
|
||||
static void on_pending_send_dialog_action_timeout_callback(void *messages_manager_ptr, int64 dialog_id_int);
|
||||
|
||||
static void on_active_dialog_action_timeout_callback(void *messages_manager_ptr, int64 dialog_id_int);
|
||||
|
||||
static void on_preload_folder_dialog_list_timeout_callback(void *messages_manager_ptr, int64 folder_id_int);
|
||||
|
||||
static void on_update_viewed_messages_timeout_callback(void *messages_manager_ptr, int64 dialog_id_int);
|
||||
@ -3274,23 +3257,6 @@ class MessagesManager final : public Actor {
|
||||
FlatHashMap<StoryFullId, FlatHashSet<MessageFullId, MessageFullIdHash>, StoryFullIdHash>
|
||||
story_to_replied_media_timestamp_messages_;
|
||||
|
||||
struct ActiveDialogAction {
|
||||
MessageId top_thread_message_id;
|
||||
DialogId typing_dialog_id;
|
||||
DialogAction action;
|
||||
double start_time;
|
||||
|
||||
ActiveDialogAction(MessageId top_thread_message_id, DialogId typing_dialog_id, DialogAction action,
|
||||
double start_time)
|
||||
: top_thread_message_id(top_thread_message_id)
|
||||
, typing_dialog_id(typing_dialog_id)
|
||||
, action(std::move(action))
|
||||
, start_time(start_time) {
|
||||
}
|
||||
};
|
||||
|
||||
FlatHashMap<DialogId, std::vector<ActiveDialogAction>, DialogIdHash> active_dialog_actions_;
|
||||
|
||||
FlatHashMap<NotificationGroupId, DialogId, NotificationGroupIdHash> notification_group_id_to_dialog_id_;
|
||||
|
||||
uint64 current_message_edit_generation_ = 0;
|
||||
@ -3343,7 +3309,6 @@ class MessagesManager final : public Actor {
|
||||
MultiTimeout pending_unload_dialog_timeout_{"PendingUnloadDialogTimeout"};
|
||||
MultiTimeout dialog_unmute_timeout_{"DialogUnmuteTimeout"};
|
||||
MultiTimeout pending_send_dialog_action_timeout_{"PendingSendDialogActionTimeout"};
|
||||
MultiTimeout active_dialog_action_timeout_{"ActiveDialogActionTimeout"};
|
||||
MultiTimeout preload_folder_dialog_list_timeout_{"PreloadFolderDialogListTimeout"};
|
||||
MultiTimeout update_viewed_messages_timeout_{"UpdateViewedMessagesTimeout"};
|
||||
MultiTimeout send_update_chat_read_inbox_timeout_{"SendUpdateChatReadInboxTimeout"};
|
||||
@ -3445,8 +3410,6 @@ class MessagesManager final : public Actor {
|
||||
};
|
||||
FlatHashMap<uint64, UnsentMediaQueue> yet_unsent_media_queues_;
|
||||
|
||||
FlatHashMap<DialogId, NetQueryRef, DialogIdHash> set_typing_query_;
|
||||
|
||||
WaitFreeHashMap<MessageFullId, FileSourceId, MessageFullIdHash> message_full_id_to_file_source_id_;
|
||||
|
||||
FlatHashMap<DialogId, int32, DialogIdHash> last_outgoing_forwarded_message_date_;
|
||||
|
@ -4016,6 +4016,7 @@ void Td::init_managers() {
|
||||
country_info_manager_actor_ = register_actor("CountryInfoManager", country_info_manager_.get());
|
||||
dialog_action_manager_ = make_unique<DialogActionManager>(this, create_reference());
|
||||
dialog_action_manager_actor_ = register_actor("DialogActionManager", dialog_action_manager_.get());
|
||||
G()->set_dialog_action_manager(dialog_action_manager_actor_.get());
|
||||
dialog_filter_manager_ = make_unique<DialogFilterManager>(this, create_reference());
|
||||
dialog_filter_manager_actor_ = register_actor("DialogFilterManager", dialog_filter_manager_.get());
|
||||
G()->set_dialog_filter_manager(dialog_filter_manager_actor_.get());
|
||||
@ -5980,8 +5981,8 @@ void Td::on_request(uint64 id, const td_api::deleteChatReplyMarkup &request) {
|
||||
|
||||
void Td::on_request(uint64 id, td_api::sendChatAction &request) {
|
||||
CREATE_OK_REQUEST_PROMISE();
|
||||
messages_manager_->send_dialog_action(DialogId(request.chat_id_), MessageId(request.message_thread_id_),
|
||||
DialogAction(std::move(request.action_)), std::move(promise));
|
||||
dialog_action_manager_->send_dialog_action(DialogId(request.chat_id_), MessageId(request.message_thread_id_),
|
||||
DialogAction(std::move(request.action_)), std::move(promise));
|
||||
}
|
||||
|
||||
void Td::on_request(uint64 id, td_api::forwardMessages &request) {
|
||||
|
@ -20,6 +20,7 @@
|
||||
#include "td/telegram/ConfigManager.h"
|
||||
#include "td/telegram/ContactsManager.h"
|
||||
#include "td/telegram/DialogAction.h"
|
||||
#include "td/telegram/DialogActionManager.h"
|
||||
#include "td/telegram/DialogFilterManager.h"
|
||||
#include "td/telegram/DialogId.h"
|
||||
#include "td/telegram/DialogInviteLink.h"
|
||||
@ -3888,29 +3889,30 @@ bool UpdatesManager::is_channel_pts_update(const telegram_api::Update *update) {
|
||||
|
||||
void UpdatesManager::on_update(tl_object_ptr<telegram_api::updateUserTyping> update, Promise<Unit> &&promise) {
|
||||
DialogId dialog_id(UserId(update->user_id_));
|
||||
td_->messages_manager_->on_dialog_action(dialog_id, MessageId(), dialog_id, DialogAction(std::move(update->action_)),
|
||||
get_short_update_date());
|
||||
td_->dialog_action_manager_->on_dialog_action(dialog_id, MessageId(), dialog_id,
|
||||
DialogAction(std::move(update->action_)), get_short_update_date());
|
||||
promise.set_value(Unit());
|
||||
}
|
||||
|
||||
void UpdatesManager::on_update(tl_object_ptr<telegram_api::updateChatUserTyping> update, Promise<Unit> &&promise) {
|
||||
td_->messages_manager_->on_dialog_action(DialogId(ChatId(update->chat_id_)), MessageId(), DialogId(update->from_id_),
|
||||
DialogAction(std::move(update->action_)), get_short_update_date());
|
||||
td_->dialog_action_manager_->on_dialog_action(DialogId(ChatId(update->chat_id_)), MessageId(),
|
||||
DialogId(update->from_id_), DialogAction(std::move(update->action_)),
|
||||
get_short_update_date());
|
||||
promise.set_value(Unit());
|
||||
}
|
||||
|
||||
void UpdatesManager::on_update(tl_object_ptr<telegram_api::updateChannelUserTyping> update, Promise<Unit> &&promise) {
|
||||
td_->messages_manager_->on_dialog_action(DialogId(ChannelId(update->channel_id_)),
|
||||
MessageId(ServerMessageId(update->top_msg_id_)), DialogId(update->from_id_),
|
||||
DialogAction(std::move(update->action_)), get_short_update_date());
|
||||
td_->dialog_action_manager_->on_dialog_action(
|
||||
DialogId(ChannelId(update->channel_id_)), MessageId(ServerMessageId(update->top_msg_id_)),
|
||||
DialogId(update->from_id_), DialogAction(std::move(update->action_)), get_short_update_date());
|
||||
promise.set_value(Unit());
|
||||
}
|
||||
|
||||
void UpdatesManager::on_update(tl_object_ptr<telegram_api::updateEncryptedChatTyping> update, Promise<Unit> &&promise) {
|
||||
SecretChatId secret_chat_id(update->chat_id_);
|
||||
UserId user_id = td_->contacts_manager_->get_secret_chat_user_id(secret_chat_id);
|
||||
td_->messages_manager_->on_dialog_action(DialogId(secret_chat_id), MessageId(), DialogId(user_id),
|
||||
DialogAction::get_typing_action(), get_short_update_date());
|
||||
td_->dialog_action_manager_->on_dialog_action(DialogId(secret_chat_id), MessageId(), DialogId(user_id),
|
||||
DialogAction::get_typing_action(), get_short_update_date());
|
||||
promise.set_value(Unit());
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user