Handle chatAction timeouts.
GitOrigin-RevId: acd087bf97f6ff39af8111b1c8d984f72f041467
This commit is contained in:
parent
8eaea5d4af
commit
52f45abf65
@ -1,6 +1,6 @@
|
|||||||
cmake_minimum_required(VERSION 3.0.2 FATAL_ERROR)
|
cmake_minimum_required(VERSION 3.0.2 FATAL_ERROR)
|
||||||
|
|
||||||
project(TDLib VERSION 1.1.5 LANGUAGES CXX C)
|
project(TDLib VERSION 1.1.6 LANGUAGES CXX C)
|
||||||
|
|
||||||
# Prevent in-source build
|
# Prevent in-source build
|
||||||
get_filename_component(TD_REAL_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}" REALPATH)
|
get_filename_component(TD_REAL_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}" REALPATH)
|
||||||
|
@ -111,7 +111,7 @@ target_link_libraries(YourTarget PRIVATE Td::TdStatic)
|
|||||||
|
|
||||||
Or you could install `TDLib` and then reference it in your CMakeLists.txt like this:
|
Or you could install `TDLib` and then reference it in your CMakeLists.txt like this:
|
||||||
```
|
```
|
||||||
find_package(Td 1.1.5 REQUIRED)
|
find_package(Td 1.1.6 REQUIRED)
|
||||||
target_link_libraries(YourTarget PRIVATE Td::TdStatic)
|
target_link_libraries(YourTarget PRIVATE Td::TdStatic)
|
||||||
```
|
```
|
||||||
See [example/cpp/CMakeLists.txt](https://github.com/tdlib/td/tree/master/example/cpp/CMakeLists.txt).
|
See [example/cpp/CMakeLists.txt](https://github.com/tdlib/td/tree/master/example/cpp/CMakeLists.txt).
|
||||||
|
@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.1 FATAL_ERROR)
|
|||||||
|
|
||||||
project(TdExample VERSION 1.0 LANGUAGES CXX)
|
project(TdExample VERSION 1.0 LANGUAGES CXX)
|
||||||
|
|
||||||
find_package(Td 1.1.5 REQUIRED)
|
find_package(Td 1.1.6 REQUIRED)
|
||||||
|
|
||||||
add_executable(tdjson_example tdjson_example.cpp)
|
add_executable(tdjson_example tdjson_example.cpp)
|
||||||
target_link_libraries(tdjson_example PRIVATE Td::TdJson)
|
target_link_libraries(tdjson_example PRIVATE Td::TdJson)
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
<PackageManifest Version="2.0.0" xmlns="http://schemas.microsoft.com/developer/vsx-schema/2011">
|
<PackageManifest Version="2.0.0" xmlns="http://schemas.microsoft.com/developer/vsx-schema/2011">
|
||||||
<Metadata>
|
<Metadata>
|
||||||
<Identity Id="TDLib.UWP" Version="1.1.5" Language="en-US" Publisher="Telegram team" />
|
<Identity Id="TDLib.UWP" Version="1.1.6" Language="en-US" Publisher="Telegram team" />
|
||||||
<DisplayName>TDLib for Universal Windows Platform</DisplayName>
|
<DisplayName>TDLib for Universal Windows Platform</DisplayName>
|
||||||
<Description>TDLib is a library for building Telegram clients</Description>
|
<Description>TDLib is a library for building Telegram clients</Description>
|
||||||
<MoreInfo>https://core.telegram.org/tdlib</MoreInfo>
|
<MoreInfo>https://core.telegram.org/tdlib</MoreInfo>
|
||||||
|
@ -4504,6 +4504,9 @@ MessagesManager::MessagesManager(Td *td, ActorShared<> parent) : td_(td), parent
|
|||||||
pending_send_dialog_action_timeout_.set_callback(on_pending_send_dialog_action_timeout_callback);
|
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));
|
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));
|
||||||
|
|
||||||
sequence_dispatcher_ = create_actor<MultiSequenceDispatcher>("multi sequence dispatcher");
|
sequence_dispatcher_ = create_actor<MultiSequenceDispatcher>("multi sequence dispatcher");
|
||||||
|
|
||||||
if (G()->parameters().use_message_db) {
|
if (G()->parameters().use_message_db) {
|
||||||
@ -4637,6 +4640,16 @@ void MessagesManager::on_pending_send_dialog_action_timeout_callback(void *messa
|
|||||||
DialogId(dialog_id_int));
|
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));
|
||||||
|
}
|
||||||
|
|
||||||
BufferSlice MessagesManager::get_dialog_database_value(const Dialog *d) {
|
BufferSlice MessagesManager::get_dialog_database_value(const Dialog *d) {
|
||||||
// can't use log_event_store, because it tries to parse stored Dialog
|
// can't use log_event_store, because it tries to parse stored Dialog
|
||||||
LogEventStorerCalcLength storer_calc_length;
|
LogEventStorerCalcLength storer_calc_length;
|
||||||
@ -5620,6 +5633,77 @@ void MessagesManager::on_update_channel_max_unavailable_message_id(ChannelId cha
|
|||||||
|
|
||||||
void MessagesManager::on_user_dialog_action(DialogId dialog_id, UserId user_id,
|
void MessagesManager::on_user_dialog_action(DialogId dialog_id, UserId user_id,
|
||||||
tl_object_ptr<td_api::ChatAction> &&action) {
|
tl_object_ptr<td_api::ChatAction> &&action) {
|
||||||
|
if (td_->auth_manager_->is_bot() || !user_id.is_valid() || is_broadcast_channel(dialog_id)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool is_canceled = action == nullptr || action->get_id() == td_api::chatActionCancel::ID;
|
||||||
|
if (is_canceled) {
|
||||||
|
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(),
|
||||||
|
[user_id](const ActiveDialogAction &action) { return action.user_id == user_id; });
|
||||||
|
if (it == active_actions.end()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
LOG(DEBUG) << "Cancel action of " << user_id << " in " << dialog_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());
|
||||||
|
}
|
||||||
|
if (action == nullptr) {
|
||||||
|
action = make_tl_object<td_api::chatActionCancel>();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
auto &active_actions = active_dialog_actions_[dialog_id];
|
||||||
|
auto it = std::find_if(active_actions.begin(), active_actions.end(),
|
||||||
|
[user_id](const ActiveDialogAction &action) { return action.user_id == user_id; });
|
||||||
|
int32 prev_action_id = 0;
|
||||||
|
int32 prev_progress = 0;
|
||||||
|
if (it != active_actions.end()) {
|
||||||
|
LOG(DEBUG) << "Re-add action of " << user_id << " in " << dialog_id;
|
||||||
|
prev_action_id = it->action_id;
|
||||||
|
prev_progress = it->progress;
|
||||||
|
active_actions.erase(it);
|
||||||
|
} else {
|
||||||
|
LOG(DEBUG) << "Add action of " << user_id << " in " << dialog_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto action_id = action->get_id();
|
||||||
|
auto progress = [&] {
|
||||||
|
switch (action_id) {
|
||||||
|
case td_api::chatActionUploadingVideo::ID:
|
||||||
|
return static_cast<td_api::chatActionUploadingVideo &>(*action).progress_;
|
||||||
|
case td_api::chatActionUploadingVoiceNote::ID:
|
||||||
|
return static_cast<td_api::chatActionUploadingVoiceNote &>(*action).progress_;
|
||||||
|
case td_api::chatActionUploadingPhoto::ID:
|
||||||
|
return static_cast<td_api::chatActionUploadingPhoto &>(*action).progress_;
|
||||||
|
case td_api::chatActionUploadingDocument::ID:
|
||||||
|
return static_cast<td_api::chatActionUploadingDocument &>(*action).progress_;
|
||||||
|
case td_api::chatActionUploadingVideoNote::ID:
|
||||||
|
return static_cast<td_api::chatActionUploadingVideoNote &>(*action).progress_;
|
||||||
|
default:
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}();
|
||||||
|
active_actions.emplace_back(user_id, action_id, Time::now());
|
||||||
|
if (action_id == prev_action_id && progress <= prev_progress) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
LOG(DEBUG) << "Send action of " << user_id << " in " << dialog_id << ": " << to_string(action);
|
||||||
send_closure(G()->td(), &Td::send_update,
|
send_closure(G()->td(), &Td::send_update,
|
||||||
make_tl_object<td_api::updateUserChatAction>(
|
make_tl_object<td_api::updateUserChatAction>(
|
||||||
dialog_id.get(), td_->contacts_manager_->get_user_id_object(user_id, "on_user_dialog_action"),
|
dialog_id.get(), td_->contacts_manager_->get_user_id_object(user_id, "on_user_dialog_action"),
|
||||||
@ -18058,12 +18142,13 @@ void MessagesManager::send_update_message_content(DialogId dialog_id, MessageId
|
|||||||
dialog_id.get(), message_id.get(), get_message_content_object(content, message_date, is_content_secret)));
|
dialog_id.get(), message_id.get(), get_message_content_object(content, message_date, is_content_secret)));
|
||||||
}
|
}
|
||||||
|
|
||||||
void MessagesManager::send_update_message_edited(FullMessageId full_message_id) const {
|
void MessagesManager::send_update_message_edited(FullMessageId full_message_id) {
|
||||||
return send_update_message_edited(full_message_id.get_dialog_id(), get_message(full_message_id));
|
return send_update_message_edited(full_message_id.get_dialog_id(), get_message(full_message_id));
|
||||||
}
|
}
|
||||||
|
|
||||||
void MessagesManager::send_update_message_edited(DialogId dialog_id, const Message *m) const {
|
void MessagesManager::send_update_message_edited(DialogId dialog_id, const Message *m) {
|
||||||
CHECK(m != nullptr);
|
CHECK(m != nullptr);
|
||||||
|
on_user_dialog_action(dialog_id, m->sender_user_id, nullptr);
|
||||||
send_closure(G()->td(), &Td::send_update,
|
send_closure(G()->td(), &Td::send_update,
|
||||||
make_tl_object<td_api::updateMessageEdited>(dialog_id.get(), m->message_id.get(), m->edit_date,
|
make_tl_object<td_api::updateMessageEdited>(dialog_id.get(), m->message_id.get(), m->edit_date,
|
||||||
get_reply_markup_object(m->reply_markup)));
|
get_reply_markup_object(m->reply_markup)));
|
||||||
@ -19323,6 +19408,33 @@ void MessagesManager::on_send_dialog_action_timeout(DialogId dialog_id) {
|
|||||||
send_dialog_action(dialog_id, std::move(action), Auto());
|
send_dialog_action(dialog_id, std::move(action), Auto());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MessagesManager::on_active_dialog_action_timeout(DialogId dialog_id) {
|
||||||
|
LOG(DEBUG) << "Receive active dialog action timeout in " << dialog_id;
|
||||||
|
Dialog *d = get_dialog(dialog_id);
|
||||||
|
CHECK(d != nullptr);
|
||||||
|
|
||||||
|
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();
|
||||||
|
while (actions_it->second[0].start_time + DIALOG_ACTION_TIMEOUT < now + 0.1) {
|
||||||
|
on_user_dialog_action(dialog_id, actions_it->second[0].user_id, nullptr);
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
tl_object_ptr<telegram_api::InputChatPhoto> MessagesManager::get_input_chat_photo(FileId file_id) const {
|
tl_object_ptr<telegram_api::InputChatPhoto> MessagesManager::get_input_chat_photo(FileId file_id) const {
|
||||||
if (!file_id.is_valid()) {
|
if (!file_id.is_valid()) {
|
||||||
return make_tl_object<telegram_api::inputChatPhotoEmpty>();
|
return make_tl_object<telegram_api::inputChatPhotoEmpty>();
|
||||||
@ -21320,6 +21432,10 @@ MessagesManager::Message *MessagesManager::add_message_to_dialog(Dialog *d, uniq
|
|||||||
message->reply_markup = nullptr;
|
message->reply_markup = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (from_update) {
|
||||||
|
on_user_dialog_action(dialog_id, message->sender_user_id, nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
unique_ptr<Message> *v = &d->messages;
|
unique_ptr<Message> *v = &d->messages;
|
||||||
while (*v != nullptr && (*v)->random_y >= message->random_y) {
|
while (*v != nullptr && (*v)->random_y >= message->random_y) {
|
||||||
if ((*v)->message_id.get() < message_id.get()) {
|
if ((*v)->message_id.get() < message_id.get()) {
|
||||||
|
@ -1792,6 +1792,8 @@ class MessagesManager : public Actor {
|
|||||||
|
|
||||||
static constexpr int32 MAX_PRELOADED_DIALOGS = 1000;
|
static constexpr int32 MAX_PRELOADED_DIALOGS = 1000;
|
||||||
|
|
||||||
|
static constexpr double DIALOG_ACTION_TIMEOUT = 5.5;
|
||||||
|
|
||||||
static constexpr const char *DELETE_MESSAGE_USER_REQUEST_SOURCE = "user request";
|
static constexpr const char *DELETE_MESSAGE_USER_REQUEST_SOURCE = "user request";
|
||||||
|
|
||||||
static constexpr bool DROP_UPDATES = false;
|
static constexpr bool DROP_UPDATES = false;
|
||||||
@ -2077,9 +2079,9 @@ class MessagesManager : public Actor {
|
|||||||
void send_update_message_content(DialogId dialog_id, MessageId message_id, const MessageContent *content,
|
void send_update_message_content(DialogId dialog_id, MessageId message_id, const MessageContent *content,
|
||||||
int32 message_date, bool is_content_secret, const char *source) const;
|
int32 message_date, bool is_content_secret, const char *source) const;
|
||||||
|
|
||||||
void send_update_message_edited(FullMessageId full_message_id) const;
|
void send_update_message_edited(FullMessageId full_message_id);
|
||||||
|
|
||||||
void send_update_message_edited(DialogId dialog_id, const Message *m) const;
|
void send_update_message_edited(DialogId dialog_id, const Message *m);
|
||||||
|
|
||||||
void send_update_delete_messages(DialogId dialog_id, vector<int64> &&message_ids, bool is_permanent,
|
void send_update_delete_messages(DialogId dialog_id, vector<int64> &&message_ids, bool is_permanent,
|
||||||
bool from_cache) const;
|
bool from_cache) const;
|
||||||
@ -2156,6 +2158,8 @@ class MessagesManager : public Actor {
|
|||||||
|
|
||||||
void on_send_dialog_action_timeout(DialogId dialog_id);
|
void on_send_dialog_action_timeout(DialogId dialog_id);
|
||||||
|
|
||||||
|
void on_active_dialog_action_timeout(DialogId dialog_id);
|
||||||
|
|
||||||
Dialog *get_dialog_by_message_id(MessageId message_id);
|
Dialog *get_dialog_by_message_id(MessageId message_id);
|
||||||
|
|
||||||
MessageId get_message_id_by_random_id(Dialog *d, int64 random_id);
|
MessageId get_message_id_by_random_id(Dialog *d, int64 random_id);
|
||||||
@ -2419,6 +2423,8 @@ class MessagesManager : public Actor {
|
|||||||
|
|
||||||
static void on_pending_send_dialog_action_timeout_callback(void *messages_manager_ptr, int64 dialog_id_int);
|
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);
|
||||||
|
|
||||||
void load_secret_thumbnail(FileId thumbnail_file_id);
|
void load_secret_thumbnail(FileId thumbnail_file_id);
|
||||||
|
|
||||||
static tl_object_ptr<telegram_api::channelAdminLogEventsFilter> get_channel_admin_log_events_filter(
|
static tl_object_ptr<telegram_api::channelAdminLogEventsFilter> get_channel_admin_log_events_filter(
|
||||||
@ -2628,6 +2634,19 @@ class MessagesManager : public Actor {
|
|||||||
|
|
||||||
std::unordered_set<FullMessageId, FullMessageIdHash> waiting_for_web_page_messages_;
|
std::unordered_set<FullMessageId, FullMessageIdHash> waiting_for_web_page_messages_;
|
||||||
|
|
||||||
|
struct ActiveDialogAction {
|
||||||
|
UserId user_id;
|
||||||
|
int32 action_id;
|
||||||
|
int32 progress;
|
||||||
|
double start_time;
|
||||||
|
|
||||||
|
ActiveDialogAction(UserId user_id, int32 action_id, double start_time)
|
||||||
|
: user_id(user_id), action_id(action_id), start_time(start_time) {
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
std::unordered_map<DialogId, std::vector<ActiveDialogAction>, DialogIdHash> active_dialog_actions_;
|
||||||
|
|
||||||
NotificationSettings users_notification_settings_;
|
NotificationSettings users_notification_settings_;
|
||||||
NotificationSettings chats_notification_settings_;
|
NotificationSettings chats_notification_settings_;
|
||||||
NotificationSettings dialogs_notification_settings_;
|
NotificationSettings dialogs_notification_settings_;
|
||||||
@ -2668,6 +2687,7 @@ class MessagesManager : public Actor {
|
|||||||
MultiTimeout pending_unload_dialog_timeout_;
|
MultiTimeout pending_unload_dialog_timeout_;
|
||||||
MultiTimeout dialog_unmute_timeout_;
|
MultiTimeout dialog_unmute_timeout_;
|
||||||
MultiTimeout pending_send_dialog_action_timeout_;
|
MultiTimeout pending_send_dialog_action_timeout_;
|
||||||
|
MultiTimeout active_dialog_action_timeout_;
|
||||||
|
|
||||||
Hints dialogs_hints_; // search dialogs by title and username
|
Hints dialogs_hints_; // search dialogs by title and username
|
||||||
|
|
||||||
|
@ -193,7 +193,7 @@ class Td final : public NetQueryCallback {
|
|||||||
static td_api::object_ptr<td_api::Object> static_request(td_api::object_ptr<td_api::Function> function);
|
static td_api::object_ptr<td_api::Object> static_request(td_api::object_ptr<td_api::Function> function);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static constexpr const char *tdlib_version = "1.1.5";
|
static constexpr const char *tdlib_version = "1.1.6";
|
||||||
static constexpr int64 ONLINE_ALARM_ID = 0;
|
static constexpr int64 ONLINE_ALARM_ID = 0;
|
||||||
static constexpr int32 ONLINE_TIMEOUT = 240;
|
static constexpr int32 ONLINE_TIMEOUT = 240;
|
||||||
static constexpr int64 PING_SERVER_ALARM_ID = -1;
|
static constexpr int64 PING_SERVER_ALARM_ID = -1;
|
||||||
|
@ -1540,6 +1540,7 @@ tl_object_ptr<td_api::ChatAction> UpdatesManager::convert_send_message_action(
|
|||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
UNREACHABLE();
|
UNREACHABLE();
|
||||||
|
return make_tl_object<td_api::chatActionTyping>();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user