Edit message media.
GitOrigin-RevId: eba2f32f4e033720ea1143463a9f3d1eae54880d
This commit is contained in:
parent
744df9f511
commit
4d5197d31c
@ -2498,32 +2498,40 @@ deleteMessages chat_id:int53 message_ids:vector<int53> revoke:Bool = Ok;
|
||||
deleteChatMessagesFromUser chat_id:int53 user_id:int32 = Ok;
|
||||
|
||||
|
||||
//@description Edits the text of a message (or a text of a game message). Non-bot users can edit messages for a limited period of time. Returns the edited message after the edit is completed on the server side
|
||||
//@description Edits the text of a message (or a text of a game message). Returns the edited message after the edit is completed on the server side
|
||||
//@chat_id The chat the message belongs to @message_id Identifier of the message @reply_markup The new message reply markup; for bots only @input_message_content New text content of the message. Should be of type InputMessageText
|
||||
editMessageText chat_id:int53 message_id:int53 reply_markup:ReplyMarkup input_message_content:InputMessageContent = Message;
|
||||
|
||||
//@description Edits the message content of a live location. Messages can be edited for a limited period of time specified in the live location. Returns the edited message after the edit is completed server-side
|
||||
//@chat_id The chat the message belongs to @message_id Identifier of the message @reply_markup Tew message reply markup; for bots only @location New location content of the message; may be null. Pass null to stop sharing the live location
|
||||
//@chat_id The chat the message belongs to @message_id Identifier of the message @reply_markup The new message reply markup; for bots only @location New location content of the message; may be null. Pass null to stop sharing the live location
|
||||
editMessageLiveLocation chat_id:int53 message_id:int53 reply_markup:ReplyMarkup location:location = Message;
|
||||
|
||||
//@description Edits the message content caption. Non-bots can edit messages for a limited period of time. Returns the edited message after the edit is completed server-side
|
||||
//@description Edits the message content of an animation, an audio, a document, a photo or a video. A message media can't be edited if the message is self-destructed or to self-destructed message. A message in a message album can be edited only to a photo or a video. Returns the edited message after the edit is completed server-side
|
||||
//@chat_id The chat the message belongs to @message_id Identifier of the message @reply_markup The new message reply markup; for bots only @input_message_content New content of the message. Must be one of the following types: InputMessageAnimation, InputMessageAudio, InputMessageDocument, InputMessagePhoto or InputMessageVideo
|
||||
editMessageMedia chat_id:int53 message_id:int53 reply_markup:ReplyMarkup input_message_content:InputMessageContent = Message;
|
||||
|
||||
//@description Edits the message content caption. Returns the edited message after the edit is completed server-side
|
||||
//@chat_id The chat the message belongs to @message_id Identifier of the message @reply_markup The new message reply markup; for bots only @caption New message content caption; 0-200 characters
|
||||
editMessageCaption chat_id:int53 message_id:int53 reply_markup:ReplyMarkup caption:formattedText = Message;
|
||||
|
||||
//@description Edits the message reply markup; for bots only. Returns the edited message after the edit is completed server-side
|
||||
//@chat_id The chat the message belongs to @message_id Identifier of the message @reply_markup New message reply markup
|
||||
//@chat_id The chat the message belongs to @message_id Identifier of the message @reply_markup The new message reply markup
|
||||
editMessageReplyMarkup chat_id:int53 message_id:int53 reply_markup:ReplyMarkup = Message;
|
||||
|
||||
//@description Edits the text of an inline text or game message sent via a bot; for bots only @inline_message_id Inline message identifier @reply_markup New message reply markup @input_message_content New text content of the message. Should be of type InputMessageText
|
||||
//@description Edits the text of an inline text or game message sent via a bot; for bots only @inline_message_id Inline message identifier @reply_markup The new message reply markup @input_message_content New text content of the message. Should be of type InputMessageText
|
||||
editInlineMessageText inline_message_id:string reply_markup:ReplyMarkup input_message_content:InputMessageContent = Ok;
|
||||
|
||||
//@description Edits the content of a live location in an inline message sent via a bot; for bots only @inline_message_id Inline message identifier @reply_markup New message reply markup @location New location content of the message; may be null. Pass null to stop sharing the live location
|
||||
//@description Edits the content of a live location in an inline message sent via a bot; for bots only @inline_message_id Inline message identifier @reply_markup The new message reply markup @location New location content of the message; may be null. Pass null to stop sharing the live location
|
||||
editInlineMessageLiveLocation inline_message_id:string reply_markup:ReplyMarkup location:location = Ok;
|
||||
|
||||
//@description Edits the caption of an inline message sent via a bot; for bots only @inline_message_id Inline message identifier @reply_markup New message reply markup @caption New message content caption; 0-200 characters
|
||||
//@description Edits the message content of an animation, an audio, a document, a photo or a video in an inline message sent via a bot; for bots only @inline_message_id Inline message identifier
|
||||
//@reply_markup The new message reply markup; for bots only @input_message_content New content of the message. Must be one of the following types: InputMessageAnimation, InputMessageAudio, InputMessageDocument, InputMessagePhoto or InputMessageVideo
|
||||
editInlineMessageMedia inline_message_id:string reply_markup:ReplyMarkup input_message_content:InputMessageContent = Ok;
|
||||
|
||||
//@description Edits the caption of an inline message sent via a bot; for bots only @inline_message_id Inline message identifier @reply_markup The new message reply markup @caption New message content caption; 0-200 characters
|
||||
editInlineMessageCaption inline_message_id:string reply_markup:ReplyMarkup caption:formattedText = Ok;
|
||||
|
||||
//@description Edits the reply markup of an inline message sent via a bot; for bots only @inline_message_id Inline message identifier @reply_markup New message reply markup
|
||||
//@description Edits the reply markup of an inline message sent via a bot; for bots only @inline_message_id Inline message identifier @reply_markup The new message reply markup
|
||||
editInlineMessageReplyMarkup inline_message_id:string reply_markup:ReplyMarkup = Ok;
|
||||
|
||||
|
||||
|
Binary file not shown.
@ -1834,6 +1834,7 @@ class SendSecretMessageActor : public NetActor {
|
||||
int64 random_id) {
|
||||
if (false && !media.empty()) {
|
||||
td->messages_manager_->on_send_secret_message_error(random_id, Status::Error(400, "FILE_PART_1_MISSING"), Auto());
|
||||
stop();
|
||||
return;
|
||||
}
|
||||
|
||||
@ -1886,6 +1887,7 @@ class SendMessageActor : public NetActorOnce {
|
||||
auto input_peer = td->messages_manager_->get_input_peer(dialog_id, AccessRights::Write);
|
||||
if (input_peer == nullptr) {
|
||||
on_error(0, Status::Error(400, "Have no write access to the chat"));
|
||||
stop();
|
||||
return;
|
||||
}
|
||||
|
||||
@ -2061,6 +2063,7 @@ class SendMultiMediaActor : public NetActorOnce {
|
||||
auto input_peer = td->messages_manager_->get_input_peer(dialog_id, AccessRights::Write);
|
||||
if (input_peer == nullptr) {
|
||||
on_error(0, Status::Error(400, "Have no write access to the chat"));
|
||||
stop();
|
||||
return;
|
||||
}
|
||||
|
||||
@ -2160,6 +2163,7 @@ class SendMediaActor : public NetActorOnce {
|
||||
auto input_peer = td->messages_manager_->get_input_peer(dialog_id, AccessRights::Write);
|
||||
if (input_peer == nullptr) {
|
||||
on_error(0, Status::Error(400, "Have no write access to the chat"));
|
||||
stop();
|
||||
return;
|
||||
}
|
||||
if (!entities.empty()) {
|
||||
@ -2210,6 +2214,10 @@ class SendMediaActor : public NetActorOnce {
|
||||
return;
|
||||
}
|
||||
td->messages_manager_->on_get_dialog_error(dialog_id_, status, "SendMediaActor");
|
||||
if (thumbnail_file_id_.is_valid()) {
|
||||
// always delete partial remote location for the thumbnail, because it can't be reused anyway
|
||||
td->file_manager_->delete_partial_remote_location(thumbnail_file_id_);
|
||||
}
|
||||
if (file_id_.is_valid()) {
|
||||
if (begins_with(status.message(), "FILE_PART_") && ends_with(status.message(), "_MISSING")) {
|
||||
td->messages_manager_->on_send_message_file_part_missing(random_id_,
|
||||
@ -2221,10 +2229,6 @@ class SendMediaActor : public NetActorOnce {
|
||||
}
|
||||
}
|
||||
}
|
||||
if (thumbnail_file_id_.is_valid()) {
|
||||
// always delete partial remote location for the thumbnail, because it can't be reused anyway
|
||||
td->file_manager_->delete_partial_remote_location(thumbnail_file_id_);
|
||||
}
|
||||
td->messages_manager_->on_send_message_fail(random_id_, std::move(status));
|
||||
}
|
||||
};
|
||||
@ -2260,6 +2264,11 @@ class UploadMediaQuery : public Td::ResultHandler {
|
||||
return on_error(id, result_ptr.move_as_error());
|
||||
}
|
||||
|
||||
if (thumbnail_file_id_.is_valid()) {
|
||||
// always delete partial remote location for the thumbnail, because it can't be reused anyway
|
||||
td->file_manager_->delete_partial_remote_location(thumbnail_file_id_);
|
||||
}
|
||||
|
||||
auto ptr = result_ptr.move_as_ok();
|
||||
LOG(INFO) << "Receive result for uploadMedia: " << to_string(ptr);
|
||||
td->messages_manager_->on_upload_message_media_success(dialog_id_, message_id_, std::move(ptr));
|
||||
@ -2272,6 +2281,10 @@ class UploadMediaQuery : public Td::ResultHandler {
|
||||
return;
|
||||
}
|
||||
td->messages_manager_->on_get_dialog_error(dialog_id_, status, "UploadMediaQuery");
|
||||
if (thumbnail_file_id_.is_valid()) {
|
||||
// always delete partial remote location for the thumbnail, because it can't be reused anyway
|
||||
td->file_manager_->delete_partial_remote_location(thumbnail_file_id_);
|
||||
}
|
||||
if (file_id_.is_valid()) {
|
||||
if (begins_with(status.message(), "FILE_PART_") && ends_with(status.message(), "_MISSING")) {
|
||||
td->messages_manager_->on_upload_message_media_file_part_missing(
|
||||
@ -2297,13 +2310,21 @@ class EditMessageActor : public NetActorOnce {
|
||||
|
||||
void send(int32 flags, DialogId dialog_id, MessageId message_id, const string &message,
|
||||
vector<tl_object_ptr<telegram_api::MessageEntity>> &&entities,
|
||||
tl_object_ptr<telegram_api::InputMedia> &&input_media,
|
||||
tl_object_ptr<telegram_api::InputGeoPoint> &&input_geo_point,
|
||||
tl_object_ptr<telegram_api::ReplyMarkup> &&reply_markup, uint64 sequence_dispatcher_id) {
|
||||
if (false && input_media != nullptr) {
|
||||
on_error(0, Status::Error(400, "FILE_PART_1_MISSING"));
|
||||
stop();
|
||||
return;
|
||||
}
|
||||
|
||||
dialog_id_ = dialog_id;
|
||||
|
||||
auto input_peer = td->messages_manager_->get_input_peer(dialog_id, AccessRights::Edit);
|
||||
if (input_peer == nullptr) {
|
||||
on_error(0, Status::Error(400, "Can't access the chat"));
|
||||
stop();
|
||||
return;
|
||||
}
|
||||
|
||||
@ -2316,6 +2337,9 @@ class EditMessageActor : public NetActorOnce {
|
||||
if (!message.empty()) {
|
||||
flags |= MessagesManager::SEND_MESSAGE_FLAG_HAS_MESSAGE;
|
||||
}
|
||||
if (input_media != nullptr) {
|
||||
flags |= telegram_api::messages_editMessage::MEDIA_MASK;
|
||||
}
|
||||
if (input_geo_point != nullptr) {
|
||||
flags |= telegram_api::messages_editMessage::GEO_POINT_MASK;
|
||||
}
|
||||
@ -2323,7 +2347,7 @@ class EditMessageActor : public NetActorOnce {
|
||||
|
||||
auto query = G()->net_query_creator().create(create_storer(telegram_api::messages_editMessage(
|
||||
flags, false /*ignored*/, false /*ignored*/, std::move(input_peer), message_id.get_server_message_id().get(),
|
||||
message, nullptr, std::move(reply_markup), std::move(entities), std::move(input_geo_point))));
|
||||
message, std::move(input_media), std::move(reply_markup), std::move(entities), std::move(input_geo_point))));
|
||||
|
||||
query->debug("send to MessagesManager::MultiSequenceDispatcher");
|
||||
send_closure(td->messages_manager_->sequence_dispatcher_, &MultiSequenceDispatcher::send_with_callback,
|
||||
@ -2367,6 +2391,7 @@ class EditInlineMessageQuery : public Td::ResultHandler {
|
||||
|
||||
void send(int32 flags, tl_object_ptr<telegram_api::inputBotInlineMessageID> input_bot_inline_message_id,
|
||||
const string &message, vector<tl_object_ptr<telegram_api::MessageEntity>> &&entities,
|
||||
tl_object_ptr<telegram_api::InputMedia> &&input_media,
|
||||
tl_object_ptr<telegram_api::InputGeoPoint> &&input_geo_point,
|
||||
tl_object_ptr<telegram_api::ReplyMarkup> &&reply_markup) {
|
||||
CHECK(input_bot_inline_message_id != nullptr);
|
||||
@ -2383,13 +2408,16 @@ class EditInlineMessageQuery : public Td::ResultHandler {
|
||||
if (input_geo_point != nullptr) {
|
||||
flags |= telegram_api::messages_editInlineBotMessage::GEO_POINT_MASK;
|
||||
}
|
||||
if (input_media != nullptr) {
|
||||
flags |= telegram_api::messages_editInlineBotMessage::MEDIA_MASK;
|
||||
}
|
||||
LOG(DEBUG) << "Edit inline message with flags " << flags;
|
||||
|
||||
auto dc_id = DcId::internal(input_bot_inline_message_id->dc_id_);
|
||||
send_query(G()->net_query_creator().create(
|
||||
create_storer(telegram_api::messages_editInlineBotMessage(
|
||||
flags, false /*ignored*/, false /*ignored*/, std::move(input_bot_inline_message_id), message, nullptr,
|
||||
std::move(reply_markup), std::move(entities), std::move(input_geo_point))),
|
||||
flags, false /*ignored*/, false /*ignored*/, std::move(input_bot_inline_message_id), message,
|
||||
std::move(input_media), std::move(reply_markup), std::move(entities), std::move(input_geo_point))),
|
||||
dc_id));
|
||||
}
|
||||
|
||||
@ -2433,6 +2461,7 @@ class SetGameScoreActor : public NetActorOnce {
|
||||
auto input_peer = td->messages_manager_->get_input_peer(dialog_id, AccessRights::Edit);
|
||||
if (input_peer == nullptr) {
|
||||
on_error(0, Status::Error(400, "Can't access the chat"));
|
||||
stop();
|
||||
return;
|
||||
}
|
||||
|
||||
@ -2611,12 +2640,14 @@ class ForwardMessagesActor : public NetActorOnce {
|
||||
auto to_input_peer = td->messages_manager_->get_input_peer(to_dialog_id, AccessRights::Write);
|
||||
if (to_input_peer == nullptr) {
|
||||
on_error(0, Status::Error(400, "Have no write access to the chat"));
|
||||
stop();
|
||||
return;
|
||||
}
|
||||
|
||||
auto from_input_peer = td->messages_manager_->get_input_peer(from_dialog_id, AccessRights::Read);
|
||||
if (from_input_peer == nullptr) {
|
||||
on_error(0, Status::Error(400, "Can't access the chat to forward messages from"));
|
||||
stop();
|
||||
return;
|
||||
}
|
||||
|
||||
@ -6749,15 +6780,16 @@ void MessagesManager::on_upload_media(FileId file_id, tl_object_ptr<telegram_api
|
||||
|
||||
Message *m = get_message(full_message_id);
|
||||
if (m == nullptr) {
|
||||
// message has already been deleted by the user or sent to inaccessible channel, do not need to send it
|
||||
// message has already been deleted by the user or sent to inaccessible channel, do not need to send or edit it
|
||||
// file upload should be already cancelled in cancel_send_message_query, it shouldn't happen
|
||||
LOG(ERROR) << "Message with a media has already been deleted";
|
||||
return;
|
||||
}
|
||||
|
||||
bool is_edit = m->message_id.is_server();
|
||||
auto dialog_id = full_message_id.get_dialog_id();
|
||||
auto can_send_status = can_send_message(dialog_id);
|
||||
if (can_send_status.is_error()) {
|
||||
if (!is_edit && can_send_status.is_error()) {
|
||||
// user has left the chat during upload of the file or lost his privileges
|
||||
LOG(INFO) << "Can't send a message to " << dialog_id << ": " << can_send_status.error();
|
||||
|
||||
@ -6806,8 +6838,20 @@ void MessagesManager::do_send_media(DialogId dialog_id, Message *m, FileId file_
|
||||
thumbnail_file_id = FileId();
|
||||
}
|
||||
CHECK(m != nullptr);
|
||||
on_message_media_uploaded(
|
||||
dialog_id, m, get_input_media(m->content.get(), std::move(input_file), std::move(input_thumbnail), m->ttl),
|
||||
|
||||
MessageContent *content = nullptr;
|
||||
if (m->message_id.is_server()) {
|
||||
content = m->edited_content.get();
|
||||
if (content == nullptr) {
|
||||
LOG(ERROR) << "Message has no edited content";
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
content = m->content.get();
|
||||
}
|
||||
|
||||
on_message_media_uploaded(dialog_id, m,
|
||||
get_input_media(content, std::move(input_file), std::move(input_thumbnail), m->ttl),
|
||||
file_id, thumbnail_file_id);
|
||||
}
|
||||
|
||||
@ -6821,6 +6865,7 @@ void MessagesManager::do_send_secret_media(DialogId dialog_id, Message *m, FileI
|
||||
|
||||
CHECK(dialog_id.get_type() == DialogType::SecretChat);
|
||||
CHECK(m != nullptr);
|
||||
CHECK(m->message_id.is_yet_unsent());
|
||||
auto layer = td_->contacts_manager_->get_secret_chat_layer(dialog_id.get_secret_chat_id());
|
||||
on_secret_message_media_uploaded(
|
||||
dialog_id, m,
|
||||
@ -6847,9 +6892,14 @@ void MessagesManager::on_upload_media_error(FileId file_id, Status status) {
|
||||
|
||||
being_uploaded_files_.erase(it);
|
||||
|
||||
bool is_edit = full_message_id.get_message_id().is_server();
|
||||
if (is_edit) {
|
||||
fail_edit_message_media(full_message_id, Status::Error(status.code() > 0 ? status.code() : 500, status.message()));
|
||||
} else {
|
||||
fail_send_message(full_message_id, status.code() > 0 ? status.code() : 500,
|
||||
status.message().str()); // TODO CHECK that status has always a code
|
||||
}
|
||||
}
|
||||
|
||||
void MessagesManager::on_load_secret_thumbnail(FileId thumbnail_file_id, BufferSlice thumbnail) {
|
||||
if (G()->close_flag()) {
|
||||
@ -6879,6 +6929,7 @@ void MessagesManager::on_load_secret_thumbnail(FileId thumbnail_file_id, BufferS
|
||||
LOG(INFO) << "Message with a media has already been deleted";
|
||||
return;
|
||||
}
|
||||
CHECK(m->message_id.is_yet_unsent());
|
||||
|
||||
if (thumbnail.empty()) {
|
||||
delete_message_content_thumbnail(m->content.get());
|
||||
@ -6921,19 +6972,21 @@ void MessagesManager::on_upload_thumbnail(FileId thumbnail_file_id,
|
||||
|
||||
Message *m = get_message(full_message_id);
|
||||
if (m == nullptr) {
|
||||
// message has already been deleted by the user or sent to inaccessible channel, do not need to send it
|
||||
// message has already been deleted by the user or sent to inaccessible channel, do not need to send or edit it
|
||||
// thumbnail file upload should be already cancelled in cancel_send_message_query
|
||||
LOG(ERROR) << "Message with a media has already been deleted";
|
||||
return;
|
||||
}
|
||||
|
||||
bool is_edit = m->message_id.is_server();
|
||||
|
||||
if (thumbnail_input_file == nullptr) {
|
||||
delete_message_content_thumbnail(m->content.get());
|
||||
delete_message_content_thumbnail(is_edit ? m->edited_content.get() : m->content.get());
|
||||
}
|
||||
|
||||
auto dialog_id = full_message_id.get_dialog_id();
|
||||
auto can_send_status = can_send_message(dialog_id);
|
||||
if (can_send_status.is_error()) {
|
||||
if (!is_edit && can_send_status.is_error()) {
|
||||
// user has left the chat during upload of the thumbnail or lost his privileges
|
||||
LOG(INFO) << "Can't send a message to " << dialog_id << ": " << can_send_status.error();
|
||||
|
||||
@ -11211,11 +11264,11 @@ bool MessagesManager::can_unload_message(const Dialog *d, const Message *m) cons
|
||||
// don't want to unload messages from opened dialogs
|
||||
// don't want to unload messages to which there are replies in yet unsent messages
|
||||
// don't want to unload messages with pending web pages
|
||||
// can't unload from memory last dialog, last database messages, yet unsent messages and active live locations
|
||||
// can't unload from memory last dialog, last database messages, yet unsent messages, being edited media messages and active live locations
|
||||
FullMessageId full_message_id{d->dialog_id, m->message_id};
|
||||
return !d->is_opened && m->message_id != d->last_message_id && m->message_id != d->last_database_message_id &&
|
||||
!m->message_id.is_yet_unsent() && active_live_location_full_message_ids_.count(full_message_id) == 0 &&
|
||||
replied_by_yet_unsent_messages_.count(full_message_id) == 0 &&
|
||||
replied_by_yet_unsent_messages_.count(full_message_id) == 0 && m->edited_content == nullptr &&
|
||||
waiting_for_web_page_messages_.count(full_message_id) == 0;
|
||||
}
|
||||
|
||||
@ -11406,6 +11459,8 @@ unique_ptr<MessagesManager::Message> MessagesManager::do_delete_message(Dialog *
|
||||
if (!only_from_memory) {
|
||||
if (message_id.is_yet_unsent()) {
|
||||
cancel_send_message_query(d->dialog_id, result);
|
||||
} else {
|
||||
cancel_edit_message_media(d->dialog_id, result.get());
|
||||
}
|
||||
|
||||
if (need_get_history && !td_->auth_manager_->is_bot() && have_input_peer(d->dialog_id, AccessRights::Read)) {
|
||||
@ -11492,6 +11547,8 @@ void MessagesManager::do_delete_all_dialog_messages(Dialog *d, unique_ptr<Messag
|
||||
|
||||
if (message_id.is_yet_unsent()) {
|
||||
cancel_send_message_query(d->dialog_id, m);
|
||||
} else {
|
||||
cancel_edit_message_media(d->dialog_id, m.get());
|
||||
}
|
||||
|
||||
switch (d->dialog_id.get_type()) {
|
||||
@ -15505,6 +15562,7 @@ MessagesManager::Message *MessagesManager::get_message_to_send(Dialog *d, Messag
|
||||
int64 MessagesManager::begin_send_message(DialogId dialog_id, const Message *m) {
|
||||
LOG(INFO) << "Begin to send " << FullMessageId(dialog_id, m->message_id) << " with random_id = " << m->random_id;
|
||||
CHECK(m->random_id != 0 && being_sent_messages_.find(m->random_id) == being_sent_messages_.end());
|
||||
CHECK(m->message_id.is_yet_unsent());
|
||||
being_sent_messages_[m->random_id] = FullMessageId(dialog_id, m->message_id);
|
||||
debug_being_sent_messages_[m->random_id] = dialog_id;
|
||||
return m->random_id;
|
||||
@ -15945,6 +16003,8 @@ void MessagesManager::cancel_send_message_query(DialogId dialog_id, unique_ptr<M
|
||||
|
||||
cancel_upload_message_content_files(m->content.get());
|
||||
|
||||
CHECK(m->edited_content == nullptr);
|
||||
|
||||
if (!m->send_query_ref.empty()) {
|
||||
LOG(INFO) << "Cancel send query for " << m->message_id;
|
||||
cancel_query(m->send_query_ref);
|
||||
@ -16424,7 +16484,7 @@ Result<MessagesManager::InputMessageContent> MessagesManager::process_input_mess
|
||||
clear_draft = input_message_text.clear_draft;
|
||||
|
||||
WebPageId web_page_id;
|
||||
if (!disable_web_page_preview &&
|
||||
if (!td_->auth_manager_->is_bot() && !disable_web_page_preview &&
|
||||
(dialog_id.get_type() != DialogType::Channel ||
|
||||
td_->contacts_manager_->get_channel_status(dialog_id.get_channel_id()).can_add_web_page_previews())) {
|
||||
web_page_id = td_->web_pages_manager_->get_web_page_by_url(
|
||||
@ -16703,7 +16763,9 @@ Result<MessagesManager::InputMessageContent> MessagesManager::process_input_mess
|
||||
return Status::Error(10, "Message TTL can be specified only in private chats");
|
||||
}
|
||||
|
||||
if (dialog_id != DialogId()) {
|
||||
TRY_STATUS(can_send_message_content(dialog_id, content.get(), false));
|
||||
}
|
||||
|
||||
return InputMessageContent{std::move(content), disable_web_page_preview, clear_draft, ttl, via_bot_user_id};
|
||||
}
|
||||
@ -16788,10 +16850,11 @@ void MessagesManager::save_send_message_logevent(DialogId dialog_id, Message *m)
|
||||
}
|
||||
|
||||
void MessagesManager::do_send_message(DialogId dialog_id, Message *m, vector<int> bad_parts) {
|
||||
LOG(INFO) << "Do send " << FullMessageId(dialog_id, m->message_id);
|
||||
bool is_edit = m->message_id.is_server();
|
||||
LOG(INFO) << "Do " << (is_edit ? "edit" : "send") << ' ' << FullMessageId(dialog_id, m->message_id);
|
||||
bool is_secret = dialog_id.get_type() == DialogType::SecretChat;
|
||||
|
||||
if (m->media_album_id != 0 && bad_parts.empty() && !is_secret) {
|
||||
if (m->media_album_id != 0 && bad_parts.empty() && !is_secret && !is_edit) {
|
||||
auto &request = pending_message_group_sends_[m->media_album_id];
|
||||
request.dialog_id = dialog_id;
|
||||
request.message_ids.push_back(m->message_id);
|
||||
@ -16800,7 +16863,8 @@ void MessagesManager::do_send_message(DialogId dialog_id, Message *m, vector<int
|
||||
request.results.push_back(Status::OK());
|
||||
}
|
||||
|
||||
auto content = m->content.get();
|
||||
auto content = is_edit ? m->edited_content.get() : m->content.get();
|
||||
CHECK(content != nullptr);
|
||||
auto content_type = content->get_id();
|
||||
if (content_type == MessageText::ID) {
|
||||
auto message_text = static_cast<const MessageText *>(content);
|
||||
@ -16862,9 +16926,29 @@ void MessagesManager::on_message_media_uploaded(DialogId dialog_id, Message *m,
|
||||
FileId thumbnail_file_id) {
|
||||
CHECK(m != nullptr);
|
||||
CHECK(input_media != nullptr);
|
||||
|
||||
auto message_id = m->message_id;
|
||||
if (message_id.is_server()) {
|
||||
auto caption = get_message_content_caption(m->edited_content.get());
|
||||
auto input_reply_markup = get_input_reply_markup(m->edited_reply_markup);
|
||||
|
||||
LOG(INFO) << "Edit media from " << message_id << " in " << dialog_id;
|
||||
auto promise = PromiseCreator::lambda([actor_id = actor_id(this), dialog_id, message_id, file_id, thumbnail_file_id,
|
||||
generation = m->edit_generation](Result<Unit> result) {
|
||||
send_closure(actor_id, &MessagesManager::on_message_media_edited, dialog_id, message_id, file_id,
|
||||
thumbnail_file_id, generation, std::move(result));
|
||||
});
|
||||
send_closure(td_->create_net_actor<EditMessageActor>(std::move(promise)), &EditMessageActor::send, 1 << 11,
|
||||
dialog_id, message_id, caption.text,
|
||||
get_input_message_entities(td_->contacts_manager_.get(), caption.entities, "edit_message_media"),
|
||||
std::move(input_media), nullptr, std::move(input_reply_markup),
|
||||
get_sequence_dispatcher_id(dialog_id, -1));
|
||||
return;
|
||||
}
|
||||
|
||||
if (m->media_album_id == 0) {
|
||||
on_media_message_ready_to_send(
|
||||
dialog_id, m->message_id,
|
||||
dialog_id, message_id,
|
||||
PromiseCreator::lambda([this, dialog_id, input_media = std::move(input_media), file_id,
|
||||
thumbnail_file_id](Result<Message *> result) mutable {
|
||||
if (result.is_error() || G()->close_flag()) {
|
||||
@ -16896,19 +16980,19 @@ void MessagesManager::on_message_media_uploaded(DialogId dialog_id, Message *m,
|
||||
case telegram_api::inputMediaUploadedPhoto::ID:
|
||||
case telegram_api::inputMediaDocumentExternal::ID:
|
||||
case telegram_api::inputMediaPhotoExternal::ID:
|
||||
LOG(INFO) << "Upload media from " << m->message_id << " in " << dialog_id;
|
||||
td_->create_handler<UploadMediaQuery>()->send(dialog_id, m->message_id, file_id, thumbnail_file_id,
|
||||
LOG(INFO) << "Upload media from " << message_id << " in " << dialog_id;
|
||||
td_->create_handler<UploadMediaQuery>()->send(dialog_id, message_id, file_id, thumbnail_file_id,
|
||||
std::move(input_media));
|
||||
break;
|
||||
case telegram_api::inputMediaDocument::ID:
|
||||
case telegram_api::inputMediaPhoto::ID:
|
||||
send_closure_later(actor_id(this), &MessagesManager::on_upload_message_media_finished, m->media_album_id,
|
||||
dialog_id, m->message_id, Status::OK());
|
||||
dialog_id, message_id, Status::OK());
|
||||
break;
|
||||
default:
|
||||
LOG(ERROR) << "Have wrong input media " << to_string(input_media);
|
||||
send_closure_later(actor_id(this), &MessagesManager::on_upload_message_media_finished, m->media_album_id,
|
||||
dialog_id, m->message_id, Status::Error(400, "Wrong input media"));
|
||||
dialog_id, message_id, Status::Error(400, "Wrong input media"));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -17712,7 +17796,7 @@ void MessagesManager::edit_message_text(FullMessageId full_message_id,
|
||||
td_->create_net_actor<EditMessageActor>(std::move(promise)), &EditMessageActor::send, flags, dialog_id,
|
||||
message_id, input_message_text.text.text,
|
||||
get_input_message_entities(td_->contacts_manager_.get(), input_message_text.text.entities, "edit_message_text"),
|
||||
nullptr, std::move(input_reply_markup), get_sequence_dispatcher_id(dialog_id, -1));
|
||||
nullptr, nullptr, std::move(input_reply_markup), get_sequence_dispatcher_id(dialog_id, -1));
|
||||
}
|
||||
|
||||
void MessagesManager::edit_message_live_location(FullMessageId full_message_id,
|
||||
@ -17762,11 +17846,146 @@ void MessagesManager::edit_message_live_location(FullMessageId full_message_id,
|
||||
flags |= telegram_api::messages_editMessage::STOP_GEO_LIVE_MASK;
|
||||
}
|
||||
send_closure(td_->create_net_actor<EditMessageActor>(std::move(promise)), &EditMessageActor::send, flags, dialog_id,
|
||||
message_id, string(), vector<tl_object_ptr<telegram_api::MessageEntity>>(),
|
||||
message_id, string(), vector<tl_object_ptr<telegram_api::MessageEntity>>(), nullptr,
|
||||
location.empty() ? nullptr : location.get_input_geo_point(), std::move(input_reply_markup),
|
||||
get_sequence_dispatcher_id(dialog_id, -1));
|
||||
}
|
||||
|
||||
void MessagesManager::cancel_edit_message_media(DialogId dialog_id, Message *m) {
|
||||
if (m->edited_content == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
cancel_upload_message_content_files(m->edited_content.get());
|
||||
|
||||
m->edited_content = nullptr;
|
||||
m->edited_reply_markup = nullptr;
|
||||
m->edit_generation = 0;
|
||||
m->edit_promise.set_error(Status::Error(400, "Cancelled"));
|
||||
}
|
||||
|
||||
void MessagesManager::on_message_media_edited(DialogId dialog_id, MessageId message_id, FileId file_id,
|
||||
FileId thumbnail_file_id, uint64 generation, Result<Unit> &&result) {
|
||||
CHECK(message_id.is_server());
|
||||
auto m = get_message({dialog_id, message_id});
|
||||
if (m == nullptr || m->edit_generation != generation) {
|
||||
// message is already deleted or was edited again
|
||||
return;
|
||||
}
|
||||
|
||||
CHECK(m->edited_content != nullptr);
|
||||
if (result.is_ok()) {
|
||||
std::swap(m->content, m->edited_content);
|
||||
update_message_content(dialog_id, m, std::move(m->edited_content),
|
||||
m->edited_content->get_id() == MessagePhoto::ID && m->content->get_id() == MessagePhoto::ID,
|
||||
true);
|
||||
} else {
|
||||
auto error_message = result.error().message();
|
||||
if (thumbnail_file_id.is_valid()) {
|
||||
// always delete partial remote location for the thumbnail, because it can't be reused anyway
|
||||
td_->file_manager_->delete_partial_remote_location(thumbnail_file_id);
|
||||
}
|
||||
if (file_id.is_valid()) {
|
||||
if (begins_with(error_message, "FILE_PART_") && ends_with(error_message, "_MISSING")) {
|
||||
do_send_message(dialog_id, m, {to_integer<int32>(error_message.substr(10))});
|
||||
return;
|
||||
}
|
||||
|
||||
if (result.error().code() != 429 && result.error().code() < 500 && !G()->close_flag()) {
|
||||
td_->file_manager_->delete_partial_remote_location(file_id);
|
||||
}
|
||||
}
|
||||
|
||||
cancel_upload_message_content_files(m->edited_content.get());
|
||||
}
|
||||
|
||||
m->edited_content = nullptr;
|
||||
m->edited_reply_markup = nullptr;
|
||||
m->edit_generation = 0;
|
||||
if (result.is_ok()) {
|
||||
m->edit_promise.set_value(Unit());
|
||||
} else {
|
||||
m->edit_promise.set_error(result.move_as_error());
|
||||
}
|
||||
}
|
||||
|
||||
void MessagesManager::edit_message_media(FullMessageId full_message_id,
|
||||
tl_object_ptr<td_api::ReplyMarkup> &&reply_markup,
|
||||
tl_object_ptr<td_api::InputMessageContent> &&input_message_content,
|
||||
Promise<Unit> &&promise) {
|
||||
if (input_message_content == nullptr) {
|
||||
return promise.set_error(Status::Error(5, "Can't edit message without new content"));
|
||||
}
|
||||
int32 new_message_content_type = input_message_content->get_id();
|
||||
if (new_message_content_type != td_api::inputMessageAnimation::ID &&
|
||||
new_message_content_type != td_api::inputMessageAudio::ID &&
|
||||
new_message_content_type != td_api::inputMessageDocument::ID &&
|
||||
new_message_content_type != td_api::inputMessagePhoto::ID &&
|
||||
new_message_content_type != td_api::inputMessageVideo::ID) {
|
||||
return promise.set_error(Status::Error(5, "Unsupported input message content type"));
|
||||
}
|
||||
|
||||
LOG(INFO) << "Begin to edit media of " << full_message_id;
|
||||
auto dialog_id = full_message_id.get_dialog_id();
|
||||
Dialog *d = get_dialog_force(dialog_id);
|
||||
if (d == nullptr) {
|
||||
return promise.set_error(Status::Error(5, "Chat not found"));
|
||||
}
|
||||
|
||||
if (!have_input_peer(dialog_id, AccessRights::Edit)) {
|
||||
return promise.set_error(Status::Error(5, "Can't access the chat"));
|
||||
}
|
||||
|
||||
auto message_id = full_message_id.get_message_id();
|
||||
Message *m = get_message_force(d, message_id);
|
||||
if (m == nullptr) {
|
||||
return promise.set_error(Status::Error(5, "Message not found"));
|
||||
}
|
||||
|
||||
if (!can_edit_message(dialog_id, m, true)) {
|
||||
return promise.set_error(Status::Error(5, "Message can't be edited"));
|
||||
}
|
||||
CHECK(message_id.is_server());
|
||||
|
||||
int32 old_message_content_type = m->content->get_id();
|
||||
if (old_message_content_type != MessageAnimation::ID && old_message_content_type != MessageAudio::ID &&
|
||||
old_message_content_type != MessageDocument::ID && old_message_content_type != MessagePhoto::ID &&
|
||||
old_message_content_type != MessageVideo::ID) {
|
||||
return promise.set_error(Status::Error(5, "There is no media in the message to edit"));
|
||||
}
|
||||
if (m->media_album_id != 0 && new_message_content_type != td_api::inputMessagePhoto::ID &&
|
||||
new_message_content_type != td_api::inputMessageVideo::ID) {
|
||||
return promise.set_error(Status::Error(5, "Message can be edit only to Photo or Video"));
|
||||
}
|
||||
if (m->ttl > 0) {
|
||||
return promise.set_error(Status::Error(5, "Can't edit media in self-destructing message"));
|
||||
}
|
||||
|
||||
auto r_input_message_content = process_input_message_content(dialog_id, std::move(input_message_content));
|
||||
if (r_input_message_content.is_error()) {
|
||||
return promise.set_error(r_input_message_content.move_as_error());
|
||||
}
|
||||
InputMessageContent content = r_input_message_content.move_as_ok();
|
||||
if (content.ttl > 0) {
|
||||
return promise.set_error(Status::Error(5, "Can't enable self-destruction for media"));
|
||||
}
|
||||
|
||||
auto r_new_reply_markup = get_reply_markup(std::move(reply_markup), td_->auth_manager_->is_bot(), true, false,
|
||||
!is_broadcast_channel(dialog_id));
|
||||
if (r_new_reply_markup.is_error()) {
|
||||
return promise.set_error(r_new_reply_markup.move_as_error());
|
||||
}
|
||||
|
||||
cancel_edit_message_media(dialog_id, m);
|
||||
|
||||
m->edited_content = dup_message_content(dialog_id, content.content.get(), false);
|
||||
m->edited_reply_markup = r_new_reply_markup.move_as_ok();
|
||||
m->edit_generation = ++current_message_edit_generation_;
|
||||
m->edit_promise = std::move(promise);
|
||||
|
||||
do_send_message(dialog_id, m);
|
||||
}
|
||||
|
||||
void MessagesManager::edit_message_caption(FullMessageId full_message_id,
|
||||
tl_object_ptr<td_api::ReplyMarkup> &&reply_markup,
|
||||
tl_object_ptr<td_api::formattedText> &&input_caption,
|
||||
@ -17813,7 +18032,7 @@ void MessagesManager::edit_message_caption(FullMessageId full_message_id,
|
||||
send_closure(td_->create_net_actor<EditMessageActor>(std::move(promise)), &EditMessageActor::send, 1 << 11, dialog_id,
|
||||
message_id, caption.text,
|
||||
get_input_message_entities(td_->contacts_manager_.get(), caption.entities, "edit_message_caption"),
|
||||
nullptr, std::move(input_reply_markup), get_sequence_dispatcher_id(dialog_id, -1));
|
||||
nullptr, nullptr, std::move(input_reply_markup), get_sequence_dispatcher_id(dialog_id, -1));
|
||||
}
|
||||
|
||||
void MessagesManager::edit_message_reply_markup(FullMessageId full_message_id,
|
||||
@ -17851,7 +18070,7 @@ void MessagesManager::edit_message_reply_markup(FullMessageId full_message_id,
|
||||
}
|
||||
auto input_reply_markup = get_input_reply_markup(r_new_reply_markup.ok());
|
||||
send_closure(td_->create_net_actor<EditMessageActor>(std::move(promise)), &EditMessageActor::send, 0, dialog_id,
|
||||
message_id, string(), vector<tl_object_ptr<telegram_api::MessageEntity>>(), nullptr,
|
||||
message_id, string(), vector<tl_object_ptr<telegram_api::MessageEntity>>(), nullptr, nullptr,
|
||||
std::move(input_reply_markup), get_sequence_dispatcher_id(dialog_id, -1));
|
||||
}
|
||||
|
||||
@ -17896,7 +18115,7 @@ void MessagesManager::edit_inline_message_text(const string &inline_message_id,
|
||||
->send(flags, std::move(input_bot_inline_message_id), input_message_text.text.text,
|
||||
get_input_message_entities(td_->contacts_manager_.get(), input_message_text.text.entities,
|
||||
"edit_inline_message_text"),
|
||||
nullptr, get_input_reply_markup(r_new_reply_markup.ok()));
|
||||
nullptr, nullptr, get_input_reply_markup(r_new_reply_markup.ok()));
|
||||
}
|
||||
|
||||
void MessagesManager::edit_inline_message_live_location(const string &inline_message_id,
|
||||
@ -17928,10 +18147,62 @@ void MessagesManager::edit_inline_message_live_location(const string &inline_mes
|
||||
}
|
||||
td_->create_handler<EditInlineMessageQuery>(std::move(promise))
|
||||
->send(flags, std::move(input_bot_inline_message_id), "", vector<tl_object_ptr<telegram_api::MessageEntity>>(),
|
||||
location.empty() ? nullptr : location.get_input_geo_point(),
|
||||
nullptr, location.empty() ? nullptr : location.get_input_geo_point(),
|
||||
get_input_reply_markup(r_new_reply_markup.ok()));
|
||||
}
|
||||
|
||||
void MessagesManager::edit_inline_message_media(const string &inline_message_id,
|
||||
tl_object_ptr<td_api::ReplyMarkup> &&reply_markup,
|
||||
tl_object_ptr<td_api::InputMessageContent> &&input_message_content,
|
||||
Promise<Unit> &&promise) {
|
||||
if (!td_->auth_manager_->is_bot()) {
|
||||
return promise.set_error(Status::Error(3, "Method is available only for bots"));
|
||||
}
|
||||
|
||||
if (input_message_content == nullptr) {
|
||||
return promise.set_error(Status::Error(5, "Can't edit message without new content"));
|
||||
}
|
||||
int32 new_message_content_type = input_message_content->get_id();
|
||||
if (new_message_content_type != td_api::inputMessageAnimation::ID &&
|
||||
new_message_content_type != td_api::inputMessageAudio::ID &&
|
||||
new_message_content_type != td_api::inputMessageDocument::ID &&
|
||||
new_message_content_type != td_api::inputMessagePhoto::ID &&
|
||||
new_message_content_type != td_api::inputMessageVideo::ID) {
|
||||
return promise.set_error(Status::Error(5, "Unsupported input message content type"));
|
||||
}
|
||||
|
||||
auto r_input_message_content = process_input_message_content(DialogId(), std::move(input_message_content));
|
||||
if (r_input_message_content.is_error()) {
|
||||
return promise.set_error(r_input_message_content.move_as_error());
|
||||
}
|
||||
InputMessageContent content = r_input_message_content.move_as_ok();
|
||||
if (content.ttl > 0) {
|
||||
LOG(ERROR) << "Have message content with ttl " << content.ttl;
|
||||
return promise.set_error(Status::Error(5, "Can't enable self-destruction for media"));
|
||||
}
|
||||
|
||||
auto r_new_reply_markup = get_reply_markup(std::move(reply_markup), td_->auth_manager_->is_bot(), true, false, true);
|
||||
if (r_new_reply_markup.is_error()) {
|
||||
return promise.set_error(r_new_reply_markup.move_as_error());
|
||||
}
|
||||
|
||||
auto input_bot_inline_message_id = td_->inline_queries_manager_->get_input_bot_inline_message_id(inline_message_id);
|
||||
if (input_bot_inline_message_id == nullptr) {
|
||||
return promise.set_error(Status::Error(400, "Wrong inline message identifier specified"));
|
||||
}
|
||||
|
||||
auto input_media = get_input_media(content.content.get(), nullptr, nullptr, 0);
|
||||
if (input_media == nullptr) {
|
||||
return promise.set_error(Status::Error(400, "Wrong message content specified"));
|
||||
}
|
||||
|
||||
auto caption = get_message_content_caption(content.content.get());
|
||||
td_->create_handler<EditInlineMessageQuery>(std::move(promise))
|
||||
->send(1 << 11, std::move(input_bot_inline_message_id), caption.text,
|
||||
get_input_message_entities(td_->contacts_manager_.get(), caption.entities, "edit_inline_message_media"),
|
||||
std::move(input_media), nullptr, get_input_reply_markup(r_new_reply_markup.ok()));
|
||||
}
|
||||
|
||||
void MessagesManager::edit_inline_message_caption(const string &inline_message_id,
|
||||
tl_object_ptr<td_api::ReplyMarkup> &&reply_markup,
|
||||
tl_object_ptr<td_api::formattedText> &&input_caption,
|
||||
@ -17959,7 +18230,7 @@ void MessagesManager::edit_inline_message_caption(const string &inline_message_i
|
||||
td_->create_handler<EditInlineMessageQuery>(std::move(promise))
|
||||
->send(1 << 11, std::move(input_bot_inline_message_id), caption.text,
|
||||
get_input_message_entities(td_->contacts_manager_.get(), caption.entities, "edit_inline_message_caption"),
|
||||
nullptr, get_input_reply_markup(r_new_reply_markup.ok()));
|
||||
nullptr, nullptr, get_input_reply_markup(r_new_reply_markup.ok()));
|
||||
}
|
||||
|
||||
void MessagesManager::edit_inline_message_reply_markup(const string &inline_message_id,
|
||||
@ -17981,7 +18252,7 @@ void MessagesManager::edit_inline_message_reply_markup(const string &inline_mess
|
||||
|
||||
td_->create_handler<EditInlineMessageQuery>(std::move(promise))
|
||||
->send(0, std::move(input_bot_inline_message_id), string(), vector<tl_object_ptr<telegram_api::MessageEntity>>(),
|
||||
nullptr, get_input_reply_markup(r_new_reply_markup.ok()));
|
||||
nullptr, nullptr, get_input_reply_markup(r_new_reply_markup.ok()));
|
||||
}
|
||||
|
||||
int32 MessagesManager::get_message_flags(const Message *m) {
|
||||
@ -19737,6 +20008,23 @@ void MessagesManager::fail_send_message(FullMessageId full_message_id, int error
|
||||
}
|
||||
}
|
||||
|
||||
void MessagesManager::fail_edit_message_media(FullMessageId full_message_id, Status &&error) {
|
||||
auto dialog_id = full_message_id.get_dialog_id();
|
||||
Dialog *d = get_dialog(dialog_id);
|
||||
CHECK(d != nullptr);
|
||||
MessageId message_id = full_message_id.get_message_id();
|
||||
CHECK(message_id.is_server());
|
||||
|
||||
auto m = get_message(d, message_id);
|
||||
if (m == nullptr) {
|
||||
// message has already been deleted by the user or sent to inaccessible channel
|
||||
return;
|
||||
}
|
||||
CHECK(m->edited_content != nullptr);
|
||||
m->edit_promise.set_error(std::move(error));
|
||||
cancel_edit_message_media(dialog_id, m);
|
||||
}
|
||||
|
||||
void MessagesManager::on_update_dialog_draft_message(DialogId dialog_id,
|
||||
tl_object_ptr<telegram_api::DraftMessage> &&draft_message) {
|
||||
if (!dialog_id.is_valid()) {
|
||||
@ -23380,7 +23668,7 @@ bool MessagesManager::update_message_content(DialogId dialog_id, Message *old_me
|
||||
const bool can_delete_old_document = old_message->message_id.is_yet_unsent() && false;
|
||||
|
||||
auto old_file_id = get_message_content_file_id(old_content.get());
|
||||
bool need_finish_upload = old_file_id.is_valid() && old_message->message_id.is_yet_unsent();
|
||||
bool need_finish_upload = old_file_id.is_valid() && need_merge_files;
|
||||
if (old_content_type != new_content_type) {
|
||||
need_update = true;
|
||||
LOG(INFO) << "Message content has changed its type from " << old_content_type << " to " << new_content_type;
|
||||
|
@ -1109,6 +1109,9 @@ class MessagesManager : public Actor {
|
||||
void edit_message_live_location(FullMessageId full_message_id, tl_object_ptr<td_api::ReplyMarkup> &&reply_markup,
|
||||
tl_object_ptr<td_api::location> &&input_location, Promise<Unit> &&promise);
|
||||
|
||||
void edit_message_media(FullMessageId full_message_id, tl_object_ptr<td_api::ReplyMarkup> &&reply_markup,
|
||||
tl_object_ptr<td_api::InputMessageContent> &&input_message_content, Promise<Unit> &&promise);
|
||||
|
||||
void edit_message_caption(FullMessageId full_message_id, tl_object_ptr<td_api::ReplyMarkup> &&reply_markup,
|
||||
tl_object_ptr<td_api::formattedText> &&input_caption, Promise<Unit> &&promise);
|
||||
|
||||
@ -1123,6 +1126,10 @@ class MessagesManager : public Actor {
|
||||
tl_object_ptr<td_api::ReplyMarkup> &&reply_markup,
|
||||
tl_object_ptr<td_api::location> &&input_location, Promise<Unit> &&promise);
|
||||
|
||||
void edit_inline_message_media(const string &inline_message_id, tl_object_ptr<td_api::ReplyMarkup> &&reply_markup,
|
||||
tl_object_ptr<td_api::InputMessageContent> &&input_message_content,
|
||||
Promise<Unit> &&promise);
|
||||
|
||||
void edit_inline_message_caption(const string &inline_message_id, tl_object_ptr<td_api::ReplyMarkup> &&reply_markup,
|
||||
tl_object_ptr<td_api::formattedText> &&input_caption, Promise<Unit> &&promise);
|
||||
|
||||
@ -1541,6 +1548,11 @@ class MessagesManager : public Actor {
|
||||
|
||||
unique_ptr<ReplyMarkup> reply_markup;
|
||||
|
||||
unique_ptr<MessageContent> edited_content;
|
||||
unique_ptr<ReplyMarkup> edited_reply_markup;
|
||||
uint64 edit_generation = 0;
|
||||
Promise<Unit> edit_promise;
|
||||
|
||||
unique_ptr<Message> left;
|
||||
unique_ptr<Message> right;
|
||||
|
||||
@ -1942,6 +1954,11 @@ class MessagesManager : public Actor {
|
||||
|
||||
bool can_report_dialog(DialogId dialog_id) const;
|
||||
|
||||
void cancel_edit_message_media(DialogId dialog_id, Message *m);
|
||||
|
||||
void on_message_media_edited(DialogId dialog_id, MessageId message_id, FileId file_id, FileId thumbnail_file_id,
|
||||
uint64 generation, Result<Unit> &&result);
|
||||
|
||||
MessageId get_persistent_message_id(const Dialog *d, MessageId message_id) const;
|
||||
|
||||
static MessageId get_replied_message_id(const Message *m);
|
||||
@ -2146,6 +2163,8 @@ class MessagesManager : public Actor {
|
||||
|
||||
void fail_send_message(FullMessageId full_message_id, int error_code, const string &error_message);
|
||||
|
||||
void fail_edit_message_media(FullMessageId full_message_id, Status &&error);
|
||||
|
||||
void on_dialog_updated(DialogId dialog_id, const char *source);
|
||||
|
||||
BufferSlice get_dialog_database_value(const Dialog *d);
|
||||
@ -2839,6 +2858,8 @@ class MessagesManager : public Actor {
|
||||
|
||||
int64 current_pinned_dialog_order_ = DEFAULT_ORDER;
|
||||
|
||||
uint64 current_message_edit_generation_ = 0;
|
||||
|
||||
std::set<DialogDate> ordered_dialogs_;
|
||||
std::set<DialogDate> ordered_server_dialogs_;
|
||||
|
||||
|
@ -1282,6 +1282,31 @@ class EditMessageLiveLocationRequest : public RequestOnceActor {
|
||||
}
|
||||
};
|
||||
|
||||
class EditMessageMediaRequest : public RequestOnceActor {
|
||||
FullMessageId full_message_id_;
|
||||
tl_object_ptr<td_api::ReplyMarkup> reply_markup_;
|
||||
tl_object_ptr<td_api::InputMessageContent> input_message_content_;
|
||||
|
||||
void do_run(Promise<Unit> &&promise) override {
|
||||
td->messages_manager_->edit_message_media(full_message_id_, std::move(reply_markup_),
|
||||
std::move(input_message_content_), std::move(promise));
|
||||
}
|
||||
|
||||
void do_send_result() override {
|
||||
send_result(td->messages_manager_->get_message_object(full_message_id_));
|
||||
}
|
||||
|
||||
public:
|
||||
EditMessageMediaRequest(ActorShared<Td> td, uint64 request_id, int64 dialog_id, int64 message_id,
|
||||
tl_object_ptr<td_api::ReplyMarkup> reply_markup,
|
||||
tl_object_ptr<td_api::InputMessageContent> input_message_content)
|
||||
: RequestOnceActor(std::move(td), request_id)
|
||||
, full_message_id_(DialogId(dialog_id), MessageId(message_id))
|
||||
, reply_markup_(std::move(reply_markup))
|
||||
, input_message_content_(std::move(input_message_content)) {
|
||||
}
|
||||
};
|
||||
|
||||
class EditMessageCaptionRequest : public RequestOnceActor {
|
||||
FullMessageId full_message_id_;
|
||||
tl_object_ptr<td_api::ReplyMarkup> reply_markup_;
|
||||
@ -1370,6 +1395,27 @@ class EditInlineMessageLiveLocationRequest : public RequestOnceActor {
|
||||
}
|
||||
};
|
||||
|
||||
class EditInlineMessageMediaRequest : public RequestOnceActor {
|
||||
string inline_message_id_;
|
||||
tl_object_ptr<td_api::ReplyMarkup> reply_markup_;
|
||||
tl_object_ptr<td_api::InputMessageContent> input_message_content_;
|
||||
|
||||
void do_run(Promise<Unit> &&promise) override {
|
||||
td->messages_manager_->edit_inline_message_media(inline_message_id_, std::move(reply_markup_),
|
||||
std::move(input_message_content_), std::move(promise));
|
||||
}
|
||||
|
||||
public:
|
||||
EditInlineMessageMediaRequest(ActorShared<Td> td, uint64 request_id, string inline_message_id,
|
||||
tl_object_ptr<td_api::ReplyMarkup> reply_markup,
|
||||
tl_object_ptr<td_api::InputMessageContent> input_message_content)
|
||||
: RequestOnceActor(std::move(td), request_id)
|
||||
, inline_message_id_(std::move(inline_message_id))
|
||||
, reply_markup_(std::move(reply_markup))
|
||||
, input_message_content_(std::move(input_message_content)) {
|
||||
}
|
||||
};
|
||||
|
||||
class EditInlineMessageCaptionRequest : public RequestOnceActor {
|
||||
string inline_message_id_;
|
||||
tl_object_ptr<td_api::ReplyMarkup> reply_markup_;
|
||||
@ -5823,6 +5869,11 @@ void Td::on_request(uint64 id, td_api::editMessageLiveLocation &request) {
|
||||
std::move(request.reply_markup_), std::move(request.location_));
|
||||
}
|
||||
|
||||
void Td::on_request(uint64 id, td_api::editMessageMedia &request) {
|
||||
CREATE_REQUEST(EditMessageMediaRequest, request.chat_id_, request.message_id_, std::move(request.reply_markup_),
|
||||
std::move(request.input_message_content_));
|
||||
}
|
||||
|
||||
void Td::on_request(uint64 id, td_api::editMessageCaption &request) {
|
||||
CREATE_REQUEST(EditMessageCaptionRequest, request.chat_id_, request.message_id_, std::move(request.reply_markup_),
|
||||
std::move(request.caption_));
|
||||
@ -5848,6 +5899,13 @@ void Td::on_request(uint64 id, td_api::editInlineMessageLiveLocation &request) {
|
||||
std::move(request.reply_markup_), std::move(request.location_));
|
||||
}
|
||||
|
||||
void Td::on_request(uint64 id, td_api::editInlineMessageMedia &request) {
|
||||
CHECK_IS_BOT();
|
||||
CLEAN_INPUT_STRING(request.inline_message_id_);
|
||||
CREATE_REQUEST(EditInlineMessageMediaRequest, std::move(request.inline_message_id_), std::move(request.reply_markup_),
|
||||
std::move(request.input_message_content_));
|
||||
}
|
||||
|
||||
void Td::on_request(uint64 id, td_api::editInlineMessageCaption &request) {
|
||||
CHECK_IS_BOT();
|
||||
CLEAN_INPUT_STRING(request.inline_message_id_);
|
||||
|
@ -503,6 +503,8 @@ class Td final : public NetQueryCallback {
|
||||
|
||||
void on_request(uint64 id, td_api::editMessageLiveLocation &request);
|
||||
|
||||
void on_request(uint64 id, td_api::editMessageMedia &request);
|
||||
|
||||
void on_request(uint64 id, td_api::editMessageCaption &request);
|
||||
|
||||
void on_request(uint64 id, td_api::editMessageReplyMarkup &request);
|
||||
@ -511,6 +513,8 @@ class Td final : public NetQueryCallback {
|
||||
|
||||
void on_request(uint64 id, td_api::editInlineMessageLiveLocation &request);
|
||||
|
||||
void on_request(uint64 id, td_api::editInlineMessageMedia &request);
|
||||
|
||||
void on_request(uint64 id, td_api::editInlineMessageCaption &request);
|
||||
|
||||
void on_request(uint64 id, td_api::editInlineMessageReplyMarkup &request);
|
||||
|
@ -830,16 +830,21 @@ class CliClient final : public Actor {
|
||||
}
|
||||
#endif
|
||||
|
||||
static tl_object_ptr<td_api::formattedText> as_formatted_text(
|
||||
string text, vector<td_api::object_ptr<td_api::textEntity>> entities = {}) {
|
||||
if (entities.empty()) {
|
||||
auto parsed_text =
|
||||
execute(make_tl_object<td_api::parseTextEntities>(text, make_tl_object<td_api::textParseModeMarkdown>()));
|
||||
if (parsed_text->get_id() == td_api::formattedText::ID) {
|
||||
return td_api::move_object_as<td_api::formattedText>(parsed_text);
|
||||
}
|
||||
}
|
||||
return make_tl_object<td_api::formattedText>(text, std::move(entities));
|
||||
}
|
||||
|
||||
static tl_object_ptr<td_api::formattedText> as_caption(string caption,
|
||||
vector<td_api::object_ptr<td_api::textEntity>> entities = {}) {
|
||||
if (entities.empty()) {
|
||||
auto parsed_caption =
|
||||
execute(make_tl_object<td_api::parseTextEntities>(caption, make_tl_object<td_api::textParseModeMarkdown>()));
|
||||
if (parsed_caption->get_id() == td_api::formattedText::ID) {
|
||||
return td_api::move_object_as<td_api::formattedText>(parsed_caption);
|
||||
}
|
||||
}
|
||||
return make_tl_object<td_api::formattedText>(caption, std::move(entities));
|
||||
return as_formatted_text(caption, std::move(entities));
|
||||
}
|
||||
|
||||
tl_object_ptr<td_api::NotificationSettingsScope> get_notification_settings_scope(Slice scope) const {
|
||||
@ -2243,8 +2248,7 @@ class CliClient final : public Actor {
|
||||
|
||||
draft_message = make_tl_object<td_api::draftMessage>(
|
||||
as_message_id(reply_to_message_id),
|
||||
make_tl_object<td_api::inputMessageText>(
|
||||
make_tl_object<td_api::formattedText>(message, std::move(entities)), true, false));
|
||||
make_tl_object<td_api::inputMessageText>(as_formatted_text(message, std::move(entities)), true, false));
|
||||
}
|
||||
send_request(make_tl_object<td_api::setChatDraftMessage>(as_chat_id(chat_id), std::move(draft_message)));
|
||||
} else if (op == "tcip") {
|
||||
@ -2281,10 +2285,7 @@ class CliClient final : public Actor {
|
||||
send_message(chat_id, make_tl_object<td_api::inputMessagePhoto>(as_local_file("rgb.jpg"), nullptr, Auto(), 0,
|
||||
0, as_caption(message), 0));
|
||||
} else {
|
||||
send_message(chat_id,
|
||||
make_tl_object<td_api::inputMessageText>(
|
||||
make_tl_object<td_api::formattedText>(message, vector<tl_object_ptr<td_api::textEntity>>()),
|
||||
false, true));
|
||||
send_message(chat_id, make_tl_object<td_api::inputMessageText>(as_formatted_text(message), false, true));
|
||||
}
|
||||
}
|
||||
} else if (op == "ssm") {
|
||||
@ -2315,15 +2316,7 @@ class CliClient final : public Actor {
|
||||
message = string(5097, 'a');
|
||||
}
|
||||
|
||||
auto parsed_text =
|
||||
execute(make_tl_object<td_api::parseTextEntities>(message, make_tl_object<td_api::textParseModeMarkdown>()));
|
||||
if (parsed_text->get_id() == td_api::error::ID) {
|
||||
parsed_text = make_tl_object<td_api::formattedText>(message, vector<tl_object_ptr<td_api::textEntity>>());
|
||||
}
|
||||
|
||||
send_message(
|
||||
chat_id,
|
||||
make_tl_object<td_api::inputMessageText>(move_tl_object_as<td_api::formattedText>(parsed_text), false, true),
|
||||
send_message(chat_id, make_tl_object<td_api::inputMessageText>(as_formatted_text(message), false, true),
|
||||
op == "sms", false, as_message_id(reply_to_message_id));
|
||||
} else if (op == "alm" || op == "almr") {
|
||||
string chat_id;
|
||||
@ -2337,16 +2330,9 @@ class CliClient final : public Actor {
|
||||
std::tie(reply_to_message_id, message) = split(message);
|
||||
}
|
||||
|
||||
auto parsed_text =
|
||||
execute(make_tl_object<td_api::parseTextEntities>(message, make_tl_object<td_api::textParseModeMarkdown>()));
|
||||
if (parsed_text->get_id() == td_api::error::ID) {
|
||||
parsed_text = make_tl_object<td_api::formattedText>(message, vector<tl_object_ptr<td_api::textEntity>>());
|
||||
}
|
||||
|
||||
send_request(make_tl_object<td_api::addLocalMessage>(
|
||||
as_chat_id(chat_id), as_user_id(user_id), as_message_id(reply_to_message_id), false,
|
||||
make_tl_object<td_api::inputMessageText>(move_tl_object_as<td_api::formattedText>(parsed_text), false,
|
||||
true)));
|
||||
make_tl_object<td_api::inputMessageText>(as_formatted_text(message), false, true)));
|
||||
} else if (op == "smap" || op == "smapr") {
|
||||
string chat_id;
|
||||
string reply_to_message_id;
|
||||
@ -2373,9 +2359,66 @@ class CliClient final : public Actor {
|
||||
std::tie(message_id, message) = split(args);
|
||||
send_request(make_tl_object<td_api::editMessageText>(
|
||||
as_chat_id(chat_id), as_message_id(message_id), nullptr,
|
||||
make_tl_object<td_api::inputMessageText>(
|
||||
make_tl_object<td_api::formattedText>(message, vector<tl_object_ptr<td_api::textEntity>>()), true,
|
||||
true)));
|
||||
make_tl_object<td_api::inputMessageText>(as_formatted_text(message), true, true)));
|
||||
} else if (op == "eman") {
|
||||
string chat_id;
|
||||
string message_id;
|
||||
string animation;
|
||||
std::tie(chat_id, args) = split(args);
|
||||
std::tie(message_id, animation) = split(args);
|
||||
send_request(make_tl_object<td_api::editMessageMedia>(
|
||||
as_chat_id(chat_id), as_message_id(message_id), nullptr,
|
||||
make_tl_object<td_api::inputMessageAnimation>(as_input_file(animation), nullptr, 0, 0, 0,
|
||||
as_caption("animation"))));
|
||||
} else if (op == "emc") {
|
||||
string chat_id;
|
||||
string message_id;
|
||||
string caption;
|
||||
std::tie(chat_id, args) = split(args);
|
||||
std::tie(message_id, caption) = split(args);
|
||||
send_request(make_tl_object<td_api::editMessageCaption>(as_chat_id(chat_id), as_message_id(message_id), nullptr,
|
||||
as_caption(caption)));
|
||||
} else if (op == "emd") {
|
||||
string chat_id;
|
||||
string message_id;
|
||||
string document;
|
||||
std::tie(chat_id, args) = split(args);
|
||||
std::tie(message_id, document) = split(args);
|
||||
send_request(make_tl_object<td_api::editMessageMedia>(
|
||||
as_chat_id(chat_id), as_message_id(message_id), nullptr,
|
||||
make_tl_object<td_api::inputMessageDocument>(as_input_file(document), nullptr, as_caption(""))));
|
||||
} else if (op == "emp") {
|
||||
string chat_id;
|
||||
string message_id;
|
||||
string photo;
|
||||
std::tie(chat_id, args) = split(args);
|
||||
std::tie(message_id, photo) = split(args);
|
||||
send_request(make_tl_object<td_api::editMessageMedia>(
|
||||
as_chat_id(chat_id), as_message_id(message_id), nullptr,
|
||||
make_tl_object<td_api::inputMessagePhoto>(as_input_file(photo), as_input_thumbnail(as_input_file(photo)),
|
||||
Auto(), 0, 0, as_caption(""), 0)));
|
||||
} else if (op == "empttl") {
|
||||
string chat_id;
|
||||
string message_id;
|
||||
string photo;
|
||||
std::tie(chat_id, args) = split(args);
|
||||
std::tie(message_id, photo) = split(args);
|
||||
send_request(make_tl_object<td_api::editMessageMedia>(
|
||||
as_chat_id(chat_id), as_message_id(message_id), nullptr,
|
||||
make_tl_object<td_api::inputMessagePhoto>(as_input_file(photo), as_input_thumbnail(as_input_file(photo)),
|
||||
Auto(), 0, 0, as_caption(""), 10)));
|
||||
} else if (op == "emvt") {
|
||||
string chat_id;
|
||||
string message_id;
|
||||
string video;
|
||||
string thumbnail;
|
||||
std::tie(chat_id, args) = split(args);
|
||||
std::tie(message_id, args) = split(args);
|
||||
std::tie(video, thumbnail) = split(args);
|
||||
send_request(make_tl_object<td_api::editMessageMedia>(
|
||||
as_chat_id(chat_id), as_message_id(message_id), nullptr,
|
||||
make_tl_object<td_api::inputMessageVideo>(as_input_file(video), as_input_thumbnail(as_input_file(thumbnail)),
|
||||
Auto(), 1, 2, 3, true, as_caption(""), 0)));
|
||||
} else if (op == "emll") {
|
||||
string chat_id;
|
||||
string message_id;
|
||||
@ -3163,6 +3206,10 @@ class CliClient final : public Actor {
|
||||
fd.truncate_to_current_position(size).ignore();
|
||||
} else if (op == "SetVerbosity" || op == "SV") {
|
||||
td::Log::set_verbosity_level(to_integer<int>(args));
|
||||
} else if (op[0] == 'v' && op[1] == 'v') {
|
||||
td::Log::set_verbosity_level(static_cast<int>(op.size()));
|
||||
} else if (op[0] == 'v' && ('0' <= op[1] && op[1] <= '9')) {
|
||||
td::Log::set_verbosity_level(to_integer<int>(op.substr(1)));
|
||||
} else if (op == "q" || op == "Quit") {
|
||||
quit();
|
||||
} else if (op == "dnq" || op == "DumpNetQueries") {
|
||||
|
Loading…
Reference in New Issue
Block a user