Add td_api::resendMessages.

GitOrigin-RevId: 41c14a76aaf05745592328909e47efd5feca2437
This commit is contained in:
levlam 2019-08-11 04:05:00 +03:00
parent ee3921f959
commit 378b1df843
6 changed files with 193 additions and 30 deletions

View File

@ -3110,6 +3110,11 @@ sendInlineQueryResultMessage chat_id:int53 reply_to_message_id:int53 disable_not
//@remove_caption True, if media captions of message copies needs to be removed. Ignored if send_copy is false //@remove_caption True, if media captions of message copies needs to be removed. Ignored if send_copy is false
forwardMessages chat_id:int53 from_chat_id:int53 message_ids:vector<int53> disable_notification:Bool from_background:Bool as_album:Bool send_copy:Bool remove_caption:Bool = Messages; forwardMessages chat_id:int53 from_chat_id:int53 message_ids:vector<int53> disable_notification:Bool from_background:Bool as_album:Bool send_copy:Bool remove_caption:Bool = Messages;
//@description Resends failed to send messages. Can be called only for failed to send messages for which messageSendingStateFailed.can_retry is true and after specified in messageSendingStateFailed.retry_after time passed.
//-If a message is re-sent, the corresponding failed to send message is deleted. Returns the sent messages in the same order as the message identifiers passed in message_ids. If a message can't be re-sent, null will be returned instead of the message
//@chat_id Identifier of the chat to send messages @message_ids Identifiers of the messages to resend. Message identifiers must be in a strictly increasing order
resendMessages chat_id:int53 message_ids:vector<int53> = Messages;
//@description Changes the current TTL setting (sets a new self-destruct timer) in a secret chat and sends the corresponding message @chat_id Chat identifier @ttl New TTL value, in seconds //@description Changes the current TTL setting (sets a new self-destruct timer) in a secret chat and sends the corresponding message @chat_id Chat identifier @ttl New TTL value, in seconds
sendChatSetTtlMessage chat_id:int53 ttl:int32 = Message; sendChatSetTtlMessage chat_id:int53 ttl:int32 = Message;

Binary file not shown.

View File

@ -15552,7 +15552,7 @@ tl_object_ptr<td_api::message> MessagesManager::get_message_object(DialogId dial
tl_object_ptr<td_api::MessageSendingState> sending_state; tl_object_ptr<td_api::MessageSendingState> sending_state;
if (m->is_failed_to_send) { if (m->is_failed_to_send) {
sending_state = make_tl_object<td_api::messageSendingStateFailed>( sending_state = make_tl_object<td_api::messageSendingStateFailed>(
m->send_error_code, m->send_error_message, m->send_error_code == 429, max(m->try_resend_at - Time::now(), 0.0)); m->send_error_code, m->send_error_message, can_resend_message(m), max(m->try_resend_at - Time::now(), 0.0));
} else if (m->message_id.is_yet_unsent()) { } else if (m->message_id.is_yet_unsent()) {
sending_state = make_tl_object<td_api::messageSendingStatePending>(); sending_state = make_tl_object<td_api::messageSendingStatePending>();
} }
@ -16253,15 +16253,15 @@ Result<MessageId> MessagesManager::send_message(DialogId dialog_id, MessageId re
update_dialog_draft_message(d, nullptr, false, !need_update_dialog_pos); update_dialog_draft_message(d, nullptr, false, !need_update_dialog_pos);
} }
save_send_message_logevent(dialog_id, m);
do_send_message(dialog_id, m);
send_update_new_message(d, m); send_update_new_message(d, m);
if (need_update_dialog_pos) { if (need_update_dialog_pos) {
send_update_chat_last_message(d, "send_message"); send_update_chat_last_message(d, "send_message");
} }
auto message_id = m->message_id; return m->message_id;
save_send_message_logevent(dialog_id, m);
do_send_message(dialog_id, m);
return message_id;
} }
Result<InputMessageContent> MessagesManager::process_input_message_content( Result<InputMessageContent> MessagesManager::process_input_message_content(
@ -16338,7 +16338,7 @@ Result<vector<MessageId>> MessagesManager::send_message_group(
return Status::Error(4, "Too much messages to send as an album"); return Status::Error(4, "Too much messages to send as an album");
} }
if (input_message_contents.empty()) { if (input_message_contents.empty()) {
return Status::Error(4, "There is no messages to send"); return Status::Error(4, "There are no messages to send");
} }
Dialog *d = get_dialog_force(dialog_id); Dialog *d = get_dialog_force(dialog_id);
@ -16394,7 +16394,7 @@ Result<vector<MessageId>> MessagesManager::send_message_group(
return result; return result;
} }
void MessagesManager::save_send_message_logevent(DialogId dialog_id, Message *m) { void MessagesManager::save_send_message_logevent(DialogId dialog_id, const Message *m) {
if (!G()->parameters().use_message_db) { if (!G()->parameters().use_message_db) {
return; return;
} }
@ -16407,7 +16407,7 @@ void MessagesManager::save_send_message_logevent(DialogId dialog_id, Message *m)
m->send_message_logevent_id = binlog_add(G()->td_db()->get_binlog(), LogEvent::HandlerType::SendMessage, storer); m->send_message_logevent_id = binlog_add(G()->td_db()->get_binlog(), LogEvent::HandlerType::SendMessage, storer);
} }
void MessagesManager::do_send_message(DialogId dialog_id, Message *m, vector<int> bad_parts) { void MessagesManager::do_send_message(DialogId dialog_id, const Message *m, vector<int> bad_parts) {
bool is_edit = m->message_id.is_server(); bool is_edit = m->message_id.is_server();
LOG(INFO) << "Do " << (is_edit ? "edit" : "send") << ' ' << FullMessageId(dialog_id, m->message_id); LOG(INFO) << "Do " << (is_edit ? "edit" : "send") << ' ' << FullMessageId(dialog_id, m->message_id);
bool is_secret = dialog_id.get_type() == DialogType::SecretChat; bool is_secret = dialog_id.get_type() == DialogType::SecretChat;
@ -16484,7 +16484,7 @@ void MessagesManager::do_send_message(DialogId dialog_id, Message *m, vector<int
} }
} }
void MessagesManager::on_message_media_uploaded(DialogId dialog_id, Message *m, void MessagesManager::on_message_media_uploaded(DialogId dialog_id, const Message *m,
tl_object_ptr<telegram_api::InputMedia> &&input_media, FileId file_id, tl_object_ptr<telegram_api::InputMedia> &&input_media, FileId file_id,
FileId thumbnail_file_id) { FileId thumbnail_file_id) {
CHECK(m != nullptr); CHECK(m != nullptr);
@ -16563,7 +16563,7 @@ void MessagesManager::on_message_media_uploaded(DialogId dialog_id, Message *m,
} }
} }
void MessagesManager::on_secret_message_media_uploaded(DialogId dialog_id, Message *m, void MessagesManager::on_secret_message_media_uploaded(DialogId dialog_id, const Message *m,
SecretInputMedia &&secret_input_media, FileId file_id, SecretInputMedia &&secret_input_media, FileId file_id,
FileId thumbnail_file_id) { FileId thumbnail_file_id) {
CHECK(m != nullptr); CHECK(m != nullptr);
@ -17016,7 +17016,7 @@ class MessagesManager::SendBotStartMessageLogEvent {
}; };
void MessagesManager::save_send_bot_start_message_logevent(UserId bot_user_id, DialogId dialog_id, void MessagesManager::save_send_bot_start_message_logevent(UserId bot_user_id, DialogId dialog_id,
const string &parameter, Message *m) { const string &parameter, const Message *m) {
if (!G()->parameters().use_message_db) { if (!G()->parameters().use_message_db) {
return; return;
} }
@ -17035,7 +17035,7 @@ void MessagesManager::save_send_bot_start_message_logevent(UserId bot_user_id, D
} }
void MessagesManager::do_send_bot_start_message(UserId bot_user_id, DialogId dialog_id, const string &parameter, void MessagesManager::do_send_bot_start_message(UserId bot_user_id, DialogId dialog_id, const string &parameter,
Message *m) { const Message *m) {
LOG(INFO) << "Do send bot start " << FullMessageId(dialog_id, m->message_id) << " to bot " << bot_user_id; LOG(INFO) << "Do send bot start " << FullMessageId(dialog_id, m->message_id) << " to bot " << bot_user_id;
int64 random_id = begin_send_message(dialog_id, m); int64 random_id = begin_send_message(dialog_id, m);
@ -17118,9 +17118,8 @@ Result<MessageId> MessagesManager::send_inline_query_result_message(DialogId dia
if (to_secret) { if (to_secret) {
save_send_message_logevent(dialog_id, m); save_send_message_logevent(dialog_id, m);
auto message_id = m->message_id;
do_send_message(dialog_id, m); do_send_message(dialog_id, m);
return message_id; return m->message_id;
} }
save_send_inline_query_result_message_logevent(dialog_id, m, query_id, result_id); save_send_inline_query_result_message_logevent(dialog_id, m, query_id, result_id);
@ -17155,8 +17154,8 @@ class MessagesManager::SendInlineQueryResultMessageLogEvent {
} }
}; };
void MessagesManager::save_send_inline_query_result_message_logevent(DialogId dialog_id, Message *m, int64 query_id, void MessagesManager::save_send_inline_query_result_message_logevent(DialogId dialog_id, const Message *m,
const string &result_id) { int64 query_id, const string &result_id) {
if (!G()->parameters().use_message_db) { if (!G()->parameters().use_message_db) {
return; return;
} }
@ -17174,7 +17173,7 @@ void MessagesManager::save_send_inline_query_result_message_logevent(DialogId di
binlog_add(G()->td_db()->get_binlog(), LogEvent::HandlerType::SendInlineQueryResultMessage, storer); binlog_add(G()->td_db()->get_binlog(), LogEvent::HandlerType::SendInlineQueryResultMessage, storer);
} }
void MessagesManager::do_send_inline_query_result_message(DialogId dialog_id, Message *m, int64 query_id, void MessagesManager::do_send_inline_query_result_message(DialogId dialog_id, const Message *m, int64 query_id,
const string &result_id) { const string &result_id) {
LOG(INFO) << "Do send inline query result " << FullMessageId(dialog_id, m->message_id); LOG(INFO) << "Do send inline query result " << FullMessageId(dialog_id, m->message_id);
@ -17337,6 +17336,33 @@ bool MessagesManager::can_edit_message(DialogId dialog_id, const Message *m, boo
return false; return false;
} }
bool MessagesManager::can_resend_message(const Message *m) {
if (m->send_error_code != 429) {
return false;
}
if (m->is_bot_start_message) {
return false;
}
if (m->forward_info != nullptr || m->real_forward_from_dialog_id.is_valid()) {
// TODO implement resending of forwarded messages
return false;
}
if (m->via_bot_user_id.is_valid() || m->hide_via_bot) {
// via bot message
if (!get_message_content_game_bot_user_id(m->content.get()).is_valid()) {
// TODO implement resending via_bot messages other than games
return false;
}
}
auto content_type = m->content->get_type();
if (content_type == MessageContentType::ChatSetTtl || content_type == MessageContentType::ScreenshotTaken) {
// TODO implement resending of ChatSetTtl and ScreenshotTaken messages
return false;
}
return true;
}
bool MessagesManager::is_broadcast_channel(DialogId dialog_id) const { bool MessagesManager::is_broadcast_channel(DialogId dialog_id) const {
if (dialog_id.get_type() != DialogType::Channel) { if (dialog_id.get_type() != DialogType::Channel) {
return false; return false;
@ -18407,7 +18433,7 @@ Result<vector<MessageId>> MessagesManager::forward_messages(DialogId to_dialog_i
return Status::Error(4, "Too much messages to forward"); return Status::Error(4, "Too much messages to forward");
} }
if (message_ids.empty()) { if (message_ids.empty()) {
return Status::Error(4, "There is no messages to forward"); return Status::Error(4, "There are no messages to forward");
} }
Dialog *from_dialog = get_dialog_force(from_dialog_id); Dialog *from_dialog = get_dialog_force(from_dialog_id);
@ -18480,7 +18506,7 @@ Result<vector<MessageId>> MessagesManager::forward_messages(DialogId to_dialog_i
auto content_type = content->get_type(); auto content_type = content->get_type();
bool is_game = content_type == MessageContentType::Game; bool is_game = content_type == MessageContentType::Game;
if (need_copy) { if (need_copy) {
if (is_game) { if (is_game && !get_message_content_game_bot_user_id(content.get()).is_valid()) {
LOG(INFO) << "Can't copy game from " << message_id; LOG(INFO) << "Can't copy game from " << message_id;
continue; continue;
} }
@ -18642,6 +18668,118 @@ Result<vector<MessageId>> MessagesManager::forward_messages(DialogId to_dialog_i
return result; return result;
} }
Result<vector<MessageId>> MessagesManager::resend_messages(DialogId dialog_id, vector<MessageId> message_ids) {
if (message_ids.empty()) {
return Status::Error(4, "There are no messages to resend");
}
Dialog *d = get_dialog_force(dialog_id);
if (d == nullptr) {
return Status::Error(400, "Chat not found");
}
TRY_STATUS(can_send_message(dialog_id));
MessageId last_message_id;
for (auto &message_id : message_ids) {
message_id = get_persistent_message_id(d, message_id);
const Message *m = get_message_force(d, message_id, "resend_messages");
if (m == nullptr) {
return Status::Error(400, "Message not found");
}
if (!m->is_failed_to_send) {
return Status::Error(400, "Message is not failed to send");
}
if (!can_resend_message(m)) {
return Status::Error(400, "Message can't be re-sent");
}
if (m->try_resend_at < Time::now()) {
return Status::Error(400, "Message can't be re-sent yet");
}
if (m->message_id.get() <= last_message_id.get()) {
return Status::Error(400, "Message identifiers must be in a strictly increasing order");
}
last_message_id = message_id;
}
vector<unique_ptr<MessageContent>> new_contents(message_ids.size());
std::unordered_map<int64, std::pair<int64, int32>> new_media_album_ids;
for (size_t i = 0; i < message_ids.size(); i++) {
MessageId message_id = message_ids[i];
const Message *m = get_message(d, message_id);
CHECK(m != nullptr);
unique_ptr<MessageContent> content = dup_message_content(td_, dialog_id, m->content.get(), false);
if (content == nullptr) {
LOG(INFO) << "Can't resend " << message_id;
continue;
}
auto can_send_status = can_send_message_content(dialog_id, content.get(), false);
if (can_send_status.is_error()) {
LOG(INFO) << "Can't resend " << message_id << ": " << can_send_status.message();
continue;
}
if (!get_message_content_game_bot_user_id(content.get()).is_valid()) {
// must not happen
LOG(ERROR) << "Can't resend game from " << message_id;
continue;
}
new_contents[i] = std::move(content);
if (m->media_album_id != 0) {
auto &new_media_album_id = new_media_album_ids[m->media_album_id];
new_media_album_id.second++;
if (new_media_album_id.second == 2) { // have at least 2 messages in the new album
CHECK(new_media_album_id.first == 0);
new_media_album_id.first = generate_new_media_album_id();
}
if (new_media_album_id.second == MAX_GROUPED_MESSAGES + 1) {
CHECK(new_media_album_id.first != 0);
new_media_album_id.first = 0; // just in case
}
}
}
vector<MessageId> result(message_ids.size());
bool need_update_dialog_pos = false;
for (size_t i = 0; i < message_ids.size(); i++) {
if (new_contents[i] == nullptr) {
continue;
}
unique_ptr<Message> message = delete_message(d, message_ids[i], true, &need_update_dialog_pos, "resend_messages");
CHECK(message != nullptr);
send_update_delete_messages(dialog_id, {message->message_id.get()}, true, false);
Message *m =
get_message_to_send(d, get_reply_to_message_id(d, message->reply_to_message_id), message->disable_notification,
message->from_background, std::move(new_contents[i]), &need_update_dialog_pos);
m->reply_markup = std::move(message->reply_markup);
m->via_bot_user_id = message->via_bot_user_id;
m->disable_web_page_preview = message->disable_web_page_preview;
m->clear_draft = false; // never clear draft in resend
m->ttl = message->ttl;
m->is_content_secret = message->is_content_secret;
m->media_album_id = new_media_album_ids[message->media_album_id].first;
save_send_message_logevent(dialog_id, m);
do_send_message(dialog_id, m);
send_update_new_message(d, m);
result[i] = m->message_id;
}
if (need_update_dialog_pos) {
send_update_chat_last_message(d, "resend_messages");
}
return result;
}
Result<MessageId> MessagesManager::send_dialog_set_ttl_message(DialogId dialog_id, int32 ttl) { Result<MessageId> MessagesManager::send_dialog_set_ttl_message(DialogId dialog_id, int32 ttl) {
if (dialog_id.get_type() != DialogType::SecretChat) { if (dialog_id.get_type() != DialogType::SecretChat) {
return Status::Error(5, "Can't set chat ttl in non-secret chat"); return Status::Error(5, "Can't set chat ttl in non-secret chat");

View File

@ -351,6 +351,8 @@ class MessagesManager : public Actor {
bool from_background, bool in_game_share, bool as_album, bool send_copy, bool from_background, bool in_game_share, bool as_album, bool send_copy,
bool remove_caption) TD_WARN_UNUSED_RESULT; bool remove_caption) TD_WARN_UNUSED_RESULT;
Result<vector<MessageId>> resend_messages(DialogId dialog_id, vector<MessageId> message_ids) TD_WARN_UNUSED_RESULT;
Result<MessageId> send_dialog_set_ttl_message(DialogId dialog_id, int32 ttl); Result<MessageId> send_dialog_set_ttl_message(DialogId dialog_id, int32 ttl);
Status send_screenshot_taken_notification_message(DialogId dialog_id); Status send_screenshot_taken_notification_message(DialogId dialog_id);
@ -918,9 +920,9 @@ class MessagesManager : public Actor {
mutable int32 last_access_date = 0; mutable int32 last_access_date = 0;
uint64 send_message_logevent_id = 0; mutable uint64 send_message_logevent_id = 0;
NetQueryRef send_query_ref; mutable NetQueryRef send_query_ref;
template <class StorerT> template <class StorerT>
void store(StorerT &storer) const; void store(StorerT &storer) const;
@ -1355,6 +1357,8 @@ class MessagesManager : public Actor {
Status can_send_message_content(DialogId dialog_id, const MessageContent *content, Status can_send_message_content(DialogId dialog_id, const MessageContent *content,
bool is_forward) const TD_WARN_UNUSED_RESULT; bool is_forward) const TD_WARN_UNUSED_RESULT;
static bool can_resend_message(const Message *m);
bool can_edit_message(DialogId dialog_id, const Message *m, bool is_editing, bool only_reply_markup = false) const; bool can_edit_message(DialogId dialog_id, const Message *m, bool is_editing, bool only_reply_markup = false) const;
bool can_report_dialog(DialogId dialog_id) const; bool can_report_dialog(DialogId dialog_id) const;
@ -1400,12 +1404,13 @@ class MessagesManager : public Actor {
tl_object_ptr<telegram_api::InputEncryptedFile> input_encrypted_file, tl_object_ptr<telegram_api::InputEncryptedFile> input_encrypted_file,
BufferSlice thumbnail); BufferSlice thumbnail);
void do_send_message(DialogId dialog_id, Message *m, vector<int> bad_parts = {}); void do_send_message(DialogId dialog_id, const Message *m, vector<int> bad_parts = {});
void on_message_media_uploaded(DialogId dialog_id, Message *m, tl_object_ptr<telegram_api::InputMedia> &&input_media, void on_message_media_uploaded(DialogId dialog_id, const Message *m,
FileId file_id, FileId thumbnail_file_id); tl_object_ptr<telegram_api::InputMedia> &&input_media, FileId file_id,
FileId thumbnail_file_id);
void on_secret_message_media_uploaded(DialogId dialog_id, Message *m, SecretInputMedia &&secret_input_media, void on_secret_message_media_uploaded(DialogId dialog_id, const Message *m, SecretInputMedia &&secret_input_media,
FileId file_id, FileId thumbnail_file_id); FileId file_id, FileId thumbnail_file_id);
void on_upload_message_media_finished(int64 media_album_id, DialogId dialog_id, MessageId message_id, Status result); void on_upload_message_media_finished(int64 media_album_id, DialogId dialog_id, MessageId message_id, Status result);
@ -1417,14 +1422,15 @@ class MessagesManager : public Actor {
void on_yet_unsent_media_queue_updated(DialogId dialog_id); void on_yet_unsent_media_queue_updated(DialogId dialog_id);
void save_send_bot_start_message_logevent(UserId bot_user_id, DialogId dialog_id, const string &parameter, void save_send_bot_start_message_logevent(UserId bot_user_id, DialogId dialog_id, const string &parameter,
Message *m); const Message *m);
void do_send_bot_start_message(UserId bot_user_id, DialogId dialog_id, const string &parameter, Message *m); void do_send_bot_start_message(UserId bot_user_id, DialogId dialog_id, const string &parameter, const Message *m);
void save_send_inline_query_result_message_logevent(DialogId dialog_id, Message *m, int64 query_id, void save_send_inline_query_result_message_logevent(DialogId dialog_id, const Message *m, int64 query_id,
const string &result_id); const string &result_id);
void do_send_inline_query_result_message(DialogId dialog_id, Message *m, int64 query_id, const string &result_id); void do_send_inline_query_result_message(DialogId dialog_id, const Message *m, int64 query_id,
const string &result_id);
uint64 save_send_screenshot_taken_notification_message_logevent(DialogId dialog_id, const Message *m); uint64 save_send_screenshot_taken_notification_message_logevent(DialogId dialog_id, const Message *m);
@ -2128,7 +2134,7 @@ class MessagesManager : public Actor {
static void add_message_dependencies(Dependencies &dependencies, DialogId dialog_id, const Message *m); static void add_message_dependencies(Dependencies &dependencies, DialogId dialog_id, const Message *m);
void save_send_message_logevent(DialogId dialog_id, Message *m); void save_send_message_logevent(DialogId dialog_id, const Message *m);
uint64 save_change_dialog_report_spam_state_on_server_logevent(DialogId dialog_id, bool is_spam_dialog); uint64 save_change_dialog_report_spam_state_on_server_logevent(DialogId dialog_id, bool is_spam_dialog);

View File

@ -5831,6 +5831,18 @@ void Td::on_request(uint64 id, const td_api::forwardMessages &request) {
messages_manager_->get_messages_object(-1, dialog_id, r_message_ids.ok())); messages_manager_->get_messages_object(-1, dialog_id, r_message_ids.ok()));
} }
void Td::on_request(uint64 id, const td_api::resendMessages &request) {
DialogId dialog_id(request.chat_id_);
auto r_message_ids =
messages_manager_->resend_messages(dialog_id, MessagesManager::get_message_ids(request.message_ids_));
if (r_message_ids.is_error()) {
return send_closure(actor_id(this), &Td::send_error, id, r_message_ids.move_as_error());
}
send_closure(actor_id(this), &Td::send_result, id,
messages_manager_->get_messages_object(-1, dialog_id, r_message_ids.ok()));
}
void Td::on_request(uint64 id, td_api::getWebPagePreview &request) { void Td::on_request(uint64 id, td_api::getWebPagePreview &request) {
CHECK_IS_USER(); CHECK_IS_USER();
CREATE_REQUEST(GetWebPagePreviewRequest, std::move(request.text_)); CREATE_REQUEST(GetWebPagePreviewRequest, std::move(request.text_));

View File

@ -612,6 +612,8 @@ class Td final : public NetQueryCallback {
void on_request(uint64 id, const td_api::forwardMessages &request); void on_request(uint64 id, const td_api::forwardMessages &request);
void on_request(uint64 id, const td_api::resendMessages &request);
void on_request(uint64 id, td_api::getWebPagePreview &request); void on_request(uint64 id, td_api::getWebPagePreview &request);
void on_request(uint64 id, td_api::getWebPageInstantView &request); void on_request(uint64 id, td_api::getWebPageInstantView &request);