Move MessageContent and InputMessageText implementations to corresponding files.

GitOrigin-RevId: d308007a3c850f1969b64a08865787ee7b340b34
This commit is contained in:
levlam 2018-09-28 23:57:34 +03:00
parent 362fc331c7
commit 4cf6aba717
20 changed files with 5106 additions and 4935 deletions

View File

@ -373,8 +373,10 @@ set(TDLIB_SOURCE
td/telegram/Global.cpp td/telegram/Global.cpp
td/telegram/HashtagHints.cpp td/telegram/HashtagHints.cpp
td/telegram/InlineQueriesManager.cpp td/telegram/InlineQueriesManager.cpp
td/telegram/InputMessageText.cpp
td/telegram/LanguagePackManager.cpp td/telegram/LanguagePackManager.cpp
td/telegram/Location.cpp td/telegram/Location.cpp
td/telegram/MessageContent.cpp
td/telegram/MessageEntity.cpp td/telegram/MessageEntity.cpp
td/telegram/MessagesDb.cpp td/telegram/MessagesDb.cpp
td/telegram/MessagesManager.cpp td/telegram/MessagesManager.cpp
@ -488,11 +490,13 @@ set(TDLIB_SOURCE
td/telegram/Global.h td/telegram/Global.h
td/telegram/HashtagHints.h td/telegram/HashtagHints.h
td/telegram/InlineQueriesManager.h td/telegram/InlineQueriesManager.h
td/telegram/InputMessageText.h
td/telegram/LanguagePackManager.h td/telegram/LanguagePackManager.h
td/telegram/Location.h td/telegram/Location.h
td/telegram/logevent/LogEvent.h td/telegram/logevent/LogEvent.h
td/telegram/logevent/LogEventHelper.h td/telegram/logevent/LogEventHelper.h
td/telegram/logevent/SecretChatEvent.h td/telegram/logevent/SecretChatEvent.h
td/telegram/MessageContent.h
td/telegram/MessageEntity.h td/telegram/MessageEntity.h
td/telegram/MessageId.h td/telegram/MessageId.h
td/telegram/MessagesDb.h td/telegram/MessagesDb.h
@ -560,6 +564,7 @@ set(TDLIB_SOURCE
td/telegram/files/FileId.hpp td/telegram/files/FileId.hpp
td/telegram/files/FileManager.hpp td/telegram/files/FileManager.hpp
td/telegram/Game.hpp td/telegram/Game.hpp
td/telegram/InputMessageText.hpp
td/telegram/MessageEntity.hpp td/telegram/MessageEntity.hpp
td/telegram/Payments.hpp td/telegram/Payments.hpp
td/telegram/Photo.hpp td/telegram/Photo.hpp

View File

@ -6,6 +6,7 @@
// //
#include "td/telegram/Contact.h" #include "td/telegram/Contact.h"
#include "td/telegram/misc.h"
#include "td/telegram/secret_api.h" #include "td/telegram/secret_api.h"
#include "td/telegram/td_api.h" #include "td/telegram/td_api.h"
#include "td/telegram/telegram_api.h" #include "td/telegram/telegram_api.h"
@ -77,4 +78,25 @@ StringBuilder &operator<<(StringBuilder &string_builder, const Contact &contact)
<< ", vCard size = " << contact.vcard_.size() << contact.user_id_ << "]"; << ", vCard size = " << contact.vcard_.size() << contact.user_id_ << "]";
} }
Result<Contact> process_input_message_contact(tl_object_ptr<td_api::InputMessageContent> &&input_message_content) {
CHECK(input_message_content != nullptr);
CHECK(input_message_content->get_id() == td_api::inputMessageContact::ID);
auto contact = std::move(static_cast<td_api::inputMessageContact *>(input_message_content.get())->contact_);
if (!clean_input_string(contact->phone_number_)) {
return Status::Error(400, "Phone number must be encoded in UTF-8");
}
if (!clean_input_string(contact->first_name_)) {
return Status::Error(400, "First name must be encoded in UTF-8");
}
if (!clean_input_string(contact->last_name_)) {
return Status::Error(400, "Last name must be encoded in UTF-8");
}
if (!clean_input_string(contact->vcard_)) {
return Status::Error(400, "vCard must be encoded in UTF-8");
}
return Contact(contact->phone_number_, contact->first_name_, contact->last_name_, contact->vcard_, contact->user_id_);
}
} // namespace td } // namespace td

View File

@ -11,6 +11,7 @@
#include "td/telegram/Version.h" #include "td/telegram/Version.h"
#include "td/utils/common.h" #include "td/utils/common.h"
#include "td/utils/Status.h"
#include "td/utils/StringBuilder.h" #include "td/utils/StringBuilder.h"
#include "td/utils/tl_helpers.h" #include "td/utils/tl_helpers.h"
@ -139,4 +140,7 @@ struct ContactHash {
} }
}; };
Result<Contact> process_input_message_contact(tl_object_ptr<td_api::InputMessageContent> &&input_message_content)
TD_WARN_UNUSED_RESULT;
} // namespace td } // namespace td

View File

@ -12,6 +12,7 @@
#include "td/telegram/AnimationsManager.h" #include "td/telegram/AnimationsManager.h"
#include "td/telegram/ContactsManager.h" #include "td/telegram/ContactsManager.h"
#include "td/telegram/DocumentsManager.h" #include "td/telegram/DocumentsManager.h"
#include "td/telegram/misc.h"
#include "td/telegram/Photo.h" #include "td/telegram/Photo.h"
#include "td/telegram/Td.h" #include "td/telegram/Td.h"
@ -122,4 +123,27 @@ StringBuilder &operator<<(StringBuilder &string_builder, const Game &game) {
<< ", photo = " << game.photo_ << ", animation_file_id = " << game.animation_file_id_ << "]"; << ", photo = " << game.photo_ << ", animation_file_id = " << game.animation_file_id_ << "]";
} }
Result<Game> process_input_message_game(const ContactsManager *contacts_manager,
tl_object_ptr<td_api::InputMessageContent> &&input_message_content) {
CHECK(input_message_content != nullptr);
CHECK(input_message_content->get_id() == td_api::inputMessageGame::ID);
auto input_message_game = move_tl_object_as<td_api::inputMessageGame>(input_message_content);
UserId bot_user_id(input_message_game->bot_user_id_);
if (!contacts_manager->have_input_user(bot_user_id)) {
return Status::Error(400, "Game owner bot is not accessible");
}
if (!clean_input_string(input_message_game->game_short_name_)) {
return Status::Error(400, "Game short name must be encoded in UTF-8");
}
// TODO validate game_short_name
if (input_message_game->game_short_name_.empty()) {
return Status::Error(400, "Game short name must be non-empty");
}
return Game(bot_user_id, std::move(input_message_game->game_short_name_));
}
} // namespace td } // namespace td

View File

@ -13,6 +13,7 @@
#include "td/telegram/UserId.h" #include "td/telegram/UserId.h"
#include "td/utils/common.h" #include "td/utils/common.h"
#include "td/utils/Status.h"
#include "td/utils/StringBuilder.h" #include "td/utils/StringBuilder.h"
#include "td/telegram/td_api.h" #include "td/telegram/td_api.h"
@ -20,6 +21,7 @@
namespace td { namespace td {
class ContactsManager;
class Td; class Td;
class Game { class Game {
@ -75,4 +77,8 @@ bool operator!=(const Game &lhs, const Game &rhs);
StringBuilder &operator<<(StringBuilder &string_builder, const Game &game); StringBuilder &operator<<(StringBuilder &string_builder, const Game &game);
Result<Game> process_input_message_game(const ContactsManager *contacts_manager,
tl_object_ptr<td_api::InputMessageContent> &&input_message_content)
TD_WARN_UNUSED_RESULT;
} // namespace td } // namespace td

View File

@ -21,6 +21,9 @@
#include "td/telegram/files/FileManager.h" #include "td/telegram/files/FileManager.h"
#include "td/telegram/Game.h" #include "td/telegram/Game.h"
#include "td/telegram/Global.h" #include "td/telegram/Global.h"
#include "td/telegram/InputMessageText.h"
#include "td/telegram/Location.h"
#include "td/telegram/MessageContent.h"
#include "td/telegram/MessageEntity.h" #include "td/telegram/MessageEntity.h"
#include "td/telegram/MessagesManager.h" #include "td/telegram/MessagesManager.h"
#include "td/telegram/misc.h" #include "td/telegram/misc.h"
@ -249,8 +252,8 @@ Result<tl_object_ptr<telegram_api::InputBotInlineMessage>> InlineQueriesManager:
auto constructor_id = input_message_content->get_id(); auto constructor_id = input_message_content->get_id();
if (constructor_id == td_api::inputMessageText::ID) { if (constructor_id == td_api::inputMessageText::ID) {
TRY_RESULT(input_message_text, MessagesManager::process_input_message_text(td_->contacts_manager_.get(), DialogId(), TRY_RESULT(input_message_text, process_input_message_text(td_->contacts_manager_.get(), DialogId(),
std::move(input_message_content), true)); std::move(input_message_content), true));
if (input_message_text.disable_web_page_preview) { if (input_message_text.disable_web_page_preview) {
flags |= telegram_api::inputBotInlineMessageText::NO_WEBPAGE_MASK; flags |= telegram_api::inputBotInlineMessageText::NO_WEBPAGE_MASK;
@ -265,16 +268,16 @@ Result<tl_object_ptr<telegram_api::InputBotInlineMessage>> InlineQueriesManager:
std::move(input_reply_markup)); std::move(input_reply_markup));
} }
if (constructor_id == td_api::inputMessageContact::ID) { if (constructor_id == td_api::inputMessageContact::ID) {
TRY_RESULT(contact, MessagesManager::process_input_message_contact(std::move(input_message_content))); TRY_RESULT(contact, process_input_message_contact(std::move(input_message_content)));
return contact.get_input_bot_inline_message_media_contact(flags, std::move(input_reply_markup)); return contact.get_input_bot_inline_message_media_contact(flags, std::move(input_reply_markup));
} }
if (constructor_id == td_api::inputMessageLocation::ID) { if (constructor_id == td_api::inputMessageLocation::ID) {
TRY_RESULT(location, MessagesManager::process_input_message_location(std::move(input_message_content))); TRY_RESULT(location, process_input_message_location(std::move(input_message_content)));
return make_tl_object<telegram_api::inputBotInlineMessageMediaGeo>(flags, location.first.get_input_geo_point(), return make_tl_object<telegram_api::inputBotInlineMessageMediaGeo>(flags, location.first.get_input_geo_point(),
location.second, std::move(input_reply_markup)); location.second, std::move(input_reply_markup));
} }
if (constructor_id == td_api::inputMessageVenue::ID) { if (constructor_id == td_api::inputMessageVenue::ID) {
TRY_RESULT(venue, MessagesManager::process_input_message_venue(std::move(input_message_content))); TRY_RESULT(venue, process_input_message_venue(std::move(input_message_content)));
return venue.get_input_bot_inline_message_media_venue(flags, std::move(input_reply_markup)); return venue.get_input_bot_inline_message_media_venue(flags, std::move(input_reply_markup));
} }
if (constructor_id == allowed_media_content_id) { if (constructor_id == allowed_media_content_id) {
@ -317,108 +320,6 @@ Result<tl_object_ptr<telegram_api::InputBotInlineMessage>> InlineQueriesManager:
return Status::Error(400, "Unallowed inline message content type"); return Status::Error(400, "Unallowed inline message content type");
} }
InlineMessageContent InlineQueriesManager::create_inline_message_content(
Td *td, FileId file_id, tl_object_ptr<telegram_api::BotInlineMessage> &&inline_message,
int32 allowed_media_content_id, Photo *photo, Game *game) {
CHECK(inline_message != nullptr);
CHECK((allowed_media_content_id == td_api::inputMessagePhoto::ID) == (photo != nullptr));
CHECK((allowed_media_content_id == td_api::inputMessageGame::ID) == (game != nullptr));
CHECK((allowed_media_content_id != td_api::inputMessagePhoto::ID &&
allowed_media_content_id != td_api::inputMessageGame::ID && allowed_media_content_id != -1) ==
file_id.is_valid());
InlineMessageContent result;
tl_object_ptr<telegram_api::ReplyMarkup> reply_markup;
result.disable_web_page_preview = false;
switch (inline_message->get_id()) {
case telegram_api::botInlineMessageText::ID: {
auto inline_message_text = move_tl_object_as<telegram_api::botInlineMessageText>(inline_message);
auto entities = get_message_entities(td->contacts_manager_.get(), std::move(inline_message_text->entities_),
"botInlineMessageText");
auto status = fix_formatted_text(inline_message_text->message_, entities, false, true, true, false);
if (status.is_error()) {
LOG(ERROR) << "Receive error " << status << " while parsing botInlineMessageText "
<< inline_message_text->message_;
break;
}
result.disable_web_page_preview =
(inline_message_text->flags_ & telegram_api::botInlineMessageText::NO_WEBPAGE_MASK) != 0;
WebPageId web_page_id;
if (!result.disable_web_page_preview) {
web_page_id =
td->web_pages_manager_->get_web_page_by_url(get_first_url(inline_message_text->message_, entities));
}
result.message_content = make_unique<MessageText>(
FormattedText{std::move(inline_message_text->message_), std::move(entities)}, web_page_id);
reply_markup = std::move(inline_message_text->reply_markup_);
break;
}
case telegram_api::botInlineMessageMediaGeo::ID: {
auto inline_message_geo = move_tl_object_as<telegram_api::botInlineMessageMediaGeo>(inline_message);
if (inline_message_geo->period_ > 0) {
result.message_content =
make_unique<MessageLiveLocation>(Location(inline_message_geo->geo_), inline_message_geo->period_);
} else {
result.message_content = make_unique<MessageLocation>(Location(inline_message_geo->geo_));
}
reply_markup = std::move(inline_message_geo->reply_markup_);
break;
}
case telegram_api::botInlineMessageMediaVenue::ID: {
auto inline_message_venue = move_tl_object_as<telegram_api::botInlineMessageMediaVenue>(inline_message);
result.message_content = make_unique<MessageVenue>(
Venue(inline_message_venue->geo_, std::move(inline_message_venue->title_),
std::move(inline_message_venue->address_), std::move(inline_message_venue->provider_),
std::move(inline_message_venue->venue_id_), std::move(inline_message_venue->venue_type_)));
reply_markup = std::move(inline_message_venue->reply_markup_);
break;
}
case telegram_api::botInlineMessageMediaContact::ID: {
auto inline_message_contact = move_tl_object_as<telegram_api::botInlineMessageMediaContact>(inline_message);
result.message_content = make_unique<MessageContact>(
Contact(std::move(inline_message_contact->phone_number_), std::move(inline_message_contact->first_name_),
std::move(inline_message_contact->last_name_), std::move(inline_message_contact->vcard_), 0));
reply_markup = std::move(inline_message_contact->reply_markup_);
break;
}
case telegram_api::botInlineMessageMediaAuto::ID: {
auto input_message_media_auto = move_tl_object_as<telegram_api::botInlineMessageMediaAuto>(inline_message);
auto caption = MessagesManager::get_message_text(td->contacts_manager_.get(), input_message_media_auto->message_,
std::move(input_message_media_auto->entities_), 0,
"register_inline_message_content");
if (allowed_media_content_id == td_api::inputMessageAnimation::ID) {
result.message_content = make_unique<MessageAnimation>(file_id, std::move(caption));
} else if (allowed_media_content_id == td_api::inputMessageAudio::ID) {
result.message_content = make_unique<MessageAudio>(file_id, std::move(caption));
} else if (allowed_media_content_id == td_api::inputMessageDocument::ID) {
result.message_content = make_unique<MessageDocument>(file_id, std::move(caption));
} else if (allowed_media_content_id == td_api::inputMessageGame::ID) {
CHECK(game != nullptr);
// TODO game->set_short_name(std::move(caption));
result.message_content = make_unique<MessageGame>(std::move(*game));
} else if (allowed_media_content_id == td_api::inputMessagePhoto::ID) {
result.message_content = make_unique<MessagePhoto>(std::move(*photo), std::move(caption));
} else if (allowed_media_content_id == td_api::inputMessageSticker::ID) {
result.message_content = make_unique<MessageSticker>(file_id);
} else if (allowed_media_content_id == td_api::inputMessageVideo::ID) {
result.message_content = make_unique<MessageVideo>(file_id, std::move(caption));
} else if (allowed_media_content_id == td_api::inputMessageVoiceNote::ID) {
result.message_content = make_unique<MessageVoiceNote>(file_id, std::move(caption), true);
} else {
LOG(WARNING) << "Unallowed bot inline message " << to_string(input_message_media_auto);
}
reply_markup = std::move(input_message_media_auto->reply_markup_);
break;
}
default:
UNREACHABLE();
}
result.message_reply_markup = get_reply_markup(std::move(reply_markup), td->auth_manager_->is_bot(), true, false);
return result;
}
bool InlineQueriesManager::register_inline_message_content( bool InlineQueriesManager::register_inline_message_content(
int64 query_id, const string &result_id, FileId file_id, int64 query_id, const string &result_id, FileId file_id,
tl_object_ptr<telegram_api::BotInlineMessage> &&inline_message, int32 allowed_media_content_id, Photo *photo, tl_object_ptr<telegram_api::BotInlineMessage> &&inline_message, int32 allowed_media_content_id, Photo *photo,

View File

@ -17,6 +17,7 @@
#include "td/telegram/DialogId.h" #include "td/telegram/DialogId.h"
#include "td/telegram/files/FileId.h" #include "td/telegram/files/FileId.h"
#include "td/telegram/Location.h" #include "td/telegram/Location.h"
#include "td/telegram/MessageContent.h"
#include "td/telegram/MessageEntity.h" #include "td/telegram/MessageEntity.h"
#include "td/telegram/net/NetQuery.h" #include "td/telegram/net/NetQuery.h"
#include "td/telegram/Photo.h" #include "td/telegram/Photo.h"
@ -33,16 +34,8 @@ namespace td {
class Td; class Td;
class MessageContent;
class Game; class Game;
struct InlineMessageContent {
unique_ptr<MessageContent> message_content;
unique_ptr<ReplyMarkup> message_reply_markup;
bool disable_web_page_preview;
};
class InlineQueriesManager : public Actor { class InlineQueriesManager : public Actor {
public: public:
InlineQueriesManager(Td *td, ActorShared<> parent); InlineQueriesManager(Td *td, ActorShared<> parent);
@ -101,10 +94,6 @@ class InlineQueriesManager : public Actor {
tl_object_ptr<td_api::ReplyMarkup> &&reply_markup_ptr, tl_object_ptr<td_api::ReplyMarkup> &&reply_markup_ptr,
int32 allowed_media_content_id) const TD_WARN_UNUSED_RESULT; int32 allowed_media_content_id) const TD_WARN_UNUSED_RESULT;
static InlineMessageContent create_inline_message_content(
Td *td, FileId file_id, tl_object_ptr<telegram_api::BotInlineMessage> &&inline_message,
int32 allowed_media_content_id, Photo *photo, Game *game);
bool register_inline_message_content(int64 query_id, const string &result_id, FileId file_id, bool register_inline_message_content(int64 query_id, const string &result_id, FileId file_id,
tl_object_ptr<telegram_api::BotInlineMessage> &&inline_message, tl_object_ptr<telegram_api::BotInlineMessage> &&inline_message,
int32 allowed_media_content_id, Photo *photo = nullptr, Game *game = nullptr); int32 allowed_media_content_id, Photo *photo = nullptr, Game *game = nullptr);

View File

@ -0,0 +1,50 @@
//
// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2018
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#include "td/telegram/InputMessageText.h"
#include "td/telegram/MessageEntity.h"
namespace td {
bool operator==(const InputMessageText &lhs, const InputMessageText &rhs) {
return lhs.text == rhs.text && lhs.disable_web_page_preview == rhs.disable_web_page_preview &&
lhs.clear_draft == rhs.clear_draft;
}
bool operator!=(const InputMessageText &lhs, const InputMessageText &rhs) {
return !(lhs == rhs);
}
Result<InputMessageText> process_input_message_text(const ContactsManager *contacts_manager, DialogId dialog_id,
tl_object_ptr<td_api::InputMessageContent> &&input_message_content,
bool is_bot, bool for_draft) {
CHECK(input_message_content != nullptr);
CHECK(input_message_content->get_id() == td_api::inputMessageText::ID);
auto input_message_text = static_cast<td_api::inputMessageText *>(input_message_content.get());
if (input_message_text->text_ == nullptr) {
if (for_draft) {
return InputMessageText{FormattedText(), input_message_text->disable_web_page_preview_,
input_message_text->clear_draft_};
}
return Status::Error(400, "Message text can't be empty");
}
TRY_RESULT(entities, get_message_entities(contacts_manager, std::move(input_message_text->text_->entities_)));
TRY_STATUS(fix_formatted_text(input_message_text->text_->text_, entities, for_draft, false,
need_skip_bot_commands(contacts_manager, dialog_id, is_bot), for_draft));
return InputMessageText{FormattedText{std::move(input_message_text->text_->text_), std::move(entities)},
input_message_text->disable_web_page_preview_, input_message_text->clear_draft_};
}
td_api::object_ptr<td_api::inputMessageText> get_input_message_text_object(const InputMessageText &input_message_text) {
return td_api::make_object<td_api::inputMessageText>(get_formatted_text_object(input_message_text.text),
input_message_text.disable_web_page_preview,
input_message_text.clear_draft);
}
} // namespace td

View File

@ -0,0 +1,39 @@
//
// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2018
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#pragma once
#include "td/telegram/DialogId.h"
#include "td/telegram/MessageEntity.h"
#include "td/telegram/td_api.h"
#include "td/utils/Status.h"
namespace td {
class ContactsManager;
class InputMessageText {
public:
FormattedText text;
bool disable_web_page_preview = false;
bool clear_draft = false;
InputMessageText() = default;
InputMessageText(FormattedText text, bool disable_web_page_preview, bool clear_draft)
: text(std::move(text)), disable_web_page_preview(disable_web_page_preview), clear_draft(clear_draft) {
}
};
bool operator==(const InputMessageText &lhs, const InputMessageText &rhs);
bool operator!=(const InputMessageText &lhs, const InputMessageText &rhs);
Result<InputMessageText> process_input_message_text(const ContactsManager *contacts_manager, DialogId dialog_id,
tl_object_ptr<td_api::InputMessageContent> &&input_message_content,
bool is_bot, bool for_draft = false) TD_WARN_UNUSED_RESULT;
td_api::object_ptr<td_api::inputMessageText> get_input_message_text_object(const InputMessageText &input_message_text);
} // namespace td

View File

@ -0,0 +1,35 @@
//
// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2018
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#pragma once
#include "td/telegram/InputMessageText.h"
#include "td/telegram/MessageEntity.hpp"
#include "td/utils/tl_helpers.h"
namespace td {
template <class StorerT>
static void store(const InputMessageText &input_message_text, StorerT &storer) {
BEGIN_STORE_FLAGS();
STORE_FLAG(input_message_text.disable_web_page_preview);
STORE_FLAG(input_message_text.clear_draft);
END_STORE_FLAGS();
store(input_message_text.text, storer);
}
template <class ParserT>
static void parse(InputMessageText &input_message_text, ParserT &parser) {
BEGIN_PARSE_FLAGS();
PARSE_FLAG(input_message_text.disable_web_page_preview);
PARSE_FLAG(input_message_text.clear_draft);
END_PARSE_FLAGS();
parse(input_message_text.text, parser);
}
} // namespace td

View File

@ -7,6 +7,7 @@
#include "td/telegram/Location.h" #include "td/telegram/Location.h"
#include "td/telegram/Global.h" #include "td/telegram/Global.h"
#include "td/telegram/misc.h"
#include "td/telegram/secret_api.h" #include "td/telegram/secret_api.h"
#include "td/telegram/td_api.h" #include "td/telegram/td_api.h"
#include "td/telegram/telegram_api.h" #include "td/telegram/telegram_api.h"
@ -187,4 +188,59 @@ StringBuilder &operator<<(StringBuilder &string_builder, const Venue &venue) {
<< ", id = " << venue.id_ << ", type = " << venue.type_ << "]"; << ", id = " << venue.id_ << ", type = " << venue.type_ << "]";
} }
Result<std::pair<Location, int32>> process_input_message_location(
tl_object_ptr<td_api::InputMessageContent> &&input_message_content) {
CHECK(input_message_content != nullptr);
CHECK(input_message_content->get_id() == td_api::inputMessageLocation::ID);
auto input_location = static_cast<const td_api::inputMessageLocation *>(input_message_content.get());
Location location(input_location->location_);
if (location.empty()) {
return Status::Error(400, "Wrong location specified");
}
constexpr int32 MIN_LIVE_LOCATION_PERIOD = 60; // seconds, server side limit
constexpr int32 MAX_LIVE_LOCATION_PERIOD = 86400; // seconds, server side limit
auto period = input_location->live_period_;
if (period != 0 && (period < MIN_LIVE_LOCATION_PERIOD || period > MAX_LIVE_LOCATION_PERIOD)) {
return Status::Error(400, "Wrong live location period specified");
}
return std::make_pair(std::move(location), period);
}
Result<Venue> process_input_message_venue(tl_object_ptr<td_api::InputMessageContent> &&input_message_content) {
CHECK(input_message_content != nullptr);
CHECK(input_message_content->get_id() == td_api::inputMessageVenue::ID);
auto venue = std::move(static_cast<td_api::inputMessageVenue *>(input_message_content.get())->venue_);
if (venue == nullptr) {
return Status::Error(400, "Venue can't be empty");
}
if (!clean_input_string(venue->title_)) {
return Status::Error(400, "Venue title must be encoded in UTF-8");
}
if (!clean_input_string(venue->address_)) {
return Status::Error(400, "Venue address must be encoded in UTF-8");
}
if (!clean_input_string(venue->provider_)) {
return Status::Error(400, "Venue provider must be encoded in UTF-8");
}
if (!clean_input_string(venue->id_)) {
return Status::Error(400, "Venue identifier must be encoded in UTF-8");
}
if (!clean_input_string(venue->type_)) {
return Status::Error(400, "Venue type must be encoded in UTF-8");
}
Venue result(venue);
if (result.empty()) {
return Status::Error(400, "Wrong venue location specified");
}
return result;
}
} // namespace td } // namespace td

View File

@ -15,6 +15,7 @@
#include "td/telegram/telegram_api.h" #include "td/telegram/telegram_api.h"
#include "td/utils/common.h" #include "td/utils/common.h"
#include "td/utils/Status.h"
#include "td/utils/StringBuilder.h" #include "td/utils/StringBuilder.h"
#include "td/utils/tl_helpers.h" #include "td/utils/tl_helpers.h"
@ -176,4 +177,10 @@ bool operator!=(const Venue &lhs, const Venue &rhs);
StringBuilder &operator<<(StringBuilder &string_builder, const Venue &venue); StringBuilder &operator<<(StringBuilder &string_builder, const Venue &venue);
Result<std::pair<Location, int32>> process_input_message_location(
td_api::object_ptr<td_api::InputMessageContent> &&input_message_content) TD_WARN_UNUSED_RESULT;
Result<Venue> process_input_message_venue(td_api::object_ptr<td_api::InputMessageContent> &&input_message_content)
TD_WARN_UNUSED_RESULT;
} // namespace td } // namespace td

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,227 @@
//
// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2018
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#pragma once
#include "td/telegram/Dependencies.h"
#include "td/telegram/DialogId.h"
#include "td/telegram/files/FileId.h"
#include "td/telegram/logevent/LogEvent.h"
#include "td/telegram/MessageEntity.h"
#include "td/telegram/MessageId.h"
#include "td/telegram/Photo.h"
#include "td/telegram/secret_api.h"
#include "td/telegram/ReplyMarkup.h"
#include "td/telegram/td_api.h"
#include "td/telegram/telegram_api.h"
#include "td/telegram/UserId.h"
#include "td/telegram/Version.h"
#include "td/telegram/WebPageId.h"
#include "td/utils/buffer.h"
#include "td/utils/common.h"
#include "td/utils/Status.h"
#include "td/utils/StringBuilder.h"
namespace td {
class Game;
struct Photo;
class Td;
class MultiPromiseActor;
enum class MessageContentType : int32 {
None = -1,
Text,
Animation,
Audio,
Document,
Photo,
Sticker,
Video,
VoiceNote,
Contact,
Location,
Venue,
ChatCreate,
ChatChangeTitle,
ChatChangePhoto,
ChatDeletePhoto,
ChatDeleteHistory,
ChatAddUsers,
ChatJoinedByLink,
ChatDeleteUser,
ChatMigrateTo,
ChannelCreate,
ChannelMigrateFrom,
PinMessage,
Game,
GameScore,
ScreenshotTaken,
ChatSetTtl,
Unsupported,
Call,
Invoice,
PaymentSuccessful,
VideoNote,
ContactRegistered,
ExpiredPhoto,
ExpiredVideo,
LiveLocation,
CustomServiceAction,
WebsiteConnected,
PassportDataSent,
PassportDataReceived
};
StringBuilder &operator<<(StringBuilder &string_builder, MessageContentType content_type);
// Do not forget to update merge_message_contents when one of the inheritors of this class changes
class MessageContent {
public:
MessageContent() = default;
MessageContent(const MessageContent &) = default;
MessageContent &operator=(const MessageContent &) = default;
MessageContent(MessageContent &&) = default;
MessageContent &operator=(MessageContent &&) = default;
virtual MessageContentType get_type() const = 0;
virtual ~MessageContent() = default;
};
struct InputMessageContent {
unique_ptr<MessageContent> content;
bool disable_web_page_preview = false;
bool clear_draft = false;
int32 ttl = 0;
UserId via_bot_user_id;
InputMessageContent(unique_ptr<MessageContent> &&content, bool disable_web_page_preview, bool clear_draft, int32 ttl,
UserId via_bot_user_id)
: content(std::move(content))
, disable_web_page_preview(disable_web_page_preview)
, clear_draft(clear_draft)
, ttl(ttl)
, via_bot_user_id(via_bot_user_id) {
}
};
struct InlineMessageContent {
unique_ptr<MessageContent> message_content;
unique_ptr<ReplyMarkup> message_reply_markup;
bool disable_web_page_preview;
};
void store_message_content(const MessageContent *content, LogEventStorerCalcLength &storer);
void store_message_content(const MessageContent *content, LogEventStorerUnsafe &storer);
void parse_message_content(unique_ptr<MessageContent> &content, LogEventParser &parser);
InlineMessageContent create_inline_message_content(Td *td, FileId file_id,
tl_object_ptr<telegram_api::BotInlineMessage> &&inline_message,
int32 allowed_media_content_id, Photo *photo, Game *game);
unique_ptr<MessageContent> create_text_message_content(string text, vector<MessageEntity> entities,
WebPageId web_page_id);
unique_ptr<MessageContent> create_contact_registered_message_content();
unique_ptr<MessageContent> create_screenshot_taken_message_content();
unique_ptr<MessageContent> create_chat_set_ttl_message_content(int32 ttl);
Result<InputMessageContent> create_input_message_content(
DialogId dialog_id, tl_object_ptr<td_api::InputMessageContent> &&input_message_content, Td *td,
FormattedText caption, FileId file_id, PhotoSize thumbnail, vector<FileId> sticker_file_ids);
SecretInputMedia get_secret_input_media(const MessageContent *content, Td *td,
tl_object_ptr<telegram_api::InputEncryptedFile> input_file,
BufferSlice thumbnail, int32 layer);
tl_object_ptr<telegram_api::InputMedia> get_input_media(const MessageContent *content, Td *td,
tl_object_ptr<telegram_api::InputFile> input_file,
tl_object_ptr<telegram_api::InputFile> input_thumbnail,
int32 ttl);
void delete_message_content_thumbnail(MessageContent *content, Td *td);
bool is_allowed_media_group_content(MessageContentType content_type);
bool can_forward_message_content(const MessageContent *content);
bool is_secret_message_content(int32 ttl, MessageContentType content_type);
bool is_service_message_content(MessageContentType content_type);
bool can_have_message_content_caption(MessageContentType content_type);
bool update_opened_message_content(MessageContent *content);
int32 get_message_content_index_mask(const MessageContent *content, const Td *td, bool is_secret, bool is_outgoing);
int32 get_message_content_new_participant_count(const MessageContent *content);
MessageId get_message_content_pinned_message_id(const MessageContent *content);
MessageId get_message_content_replied_message_id(const MessageContent *content);
UserId get_message_content_deleted_user_id(const MessageContent *content);
int32 get_message_content_live_location_period(const MessageContent *content);
WebPageId get_message_content_web_page_id(const MessageContent *content);
void set_message_content_web_page_id(MessageContent *content, WebPageId web_page_id);
void merge_message_contents(Td *td, MessageContent *old_content, MessageContent *new_content,
bool need_message_changed_warning, DialogId dialog_id, bool need_merge_files,
bool &is_content_changed, bool &need_update);
bool merge_message_content_file_id(Td *td, MessageContent *message_content, FileId new_file_id);
unique_ptr<MessageContent> get_secret_message_content(
Td *td, string message_text, tl_object_ptr<telegram_api::encryptedFile> file,
tl_object_ptr<secret_api::DecryptedMessageMedia> &&media,
vector<tl_object_ptr<secret_api::MessageEntity>> &&secret_entities, DialogId owner_dialog_id,
MultiPromiseActor &load_data_multipromise);
unique_ptr<MessageContent> get_message_content(Td *td, FormattedText message_text,
tl_object_ptr<telegram_api::MessageMedia> &&media,
DialogId owner_dialog_id, bool is_content_read, UserId via_bot_user_id,
int32 *ttl);
unique_ptr<MessageContent> dup_message_content(Td *td, DialogId dialog_id, const MessageContent *content,
bool for_forward);
unique_ptr<MessageContent> get_action_message_content(Td *td, tl_object_ptr<telegram_api::MessageAction> &&action,
DialogId owner_dialog_id, MessageId reply_to_message_id);
tl_object_ptr<td_api::MessageContent> get_message_content_object(const MessageContent *content, Td *td,
int32 message_date, bool is_content_secret);
const FormattedText *get_message_content_text(const MessageContent *content);
const FormattedText *get_message_content_caption(const MessageContent *content);
int32 get_message_content_duration(const MessageContent *content, const Td *td);
FileId get_message_content_file_id(const MessageContent *content);
void update_message_content_file_id_remote(MessageContent *content, FileId file_id);
FileId get_message_content_thumbnail_file_id(const MessageContent *content, const Td *td);
vector<FileId> get_message_content_file_ids(const MessageContent *content, const Td *td);
string get_message_content_search_text(const Td *td, const MessageContent *content);
void update_expired_message_content(unique_ptr<MessageContent> &content);
void add_message_content_dependencies(Dependencies &dependencies, const MessageContent *message_content);
} // namespace td

View File

@ -2205,6 +2205,24 @@ Status fix_formatted_text(string &text, vector<MessageEntity> &entities, bool al
return Status::OK(); return Status::OK();
} }
FormattedText get_message_text(const ContactsManager *contacts_manager, string message_text,
vector<tl_object_ptr<telegram_api::MessageEntity>> &&server_entities, int32 send_date,
const char *source) {
auto entities = get_message_entities(contacts_manager, std::move(server_entities), source);
auto status = fix_formatted_text(message_text, entities, true, true, true, false);
if (status.is_error()) {
if (send_date == 0 || send_date > 1497000000) { // approximate fix date
LOG(ERROR) << "Receive error " << status << " while parsing message from " << source << " with content \""
<< message_text << "\" sent at " << send_date << " with entities " << format::as_array(entities);
}
if (!clean_input_string(message_text)) {
message_text.clear();
}
entities.clear();
}
return FormattedText{std::move(message_text), std::move(entities)};
}
void add_formatted_text_dependencies(Dependencies &dependencies, const FormattedText *text) { void add_formatted_text_dependencies(Dependencies &dependencies, const FormattedText *text) {
if (text == nullptr) { if (text == nullptr) {
return; return;
@ -2216,4 +2234,26 @@ void add_formatted_text_dependencies(Dependencies &dependencies, const Formatted
} }
} }
bool need_skip_bot_commands(const ContactsManager *contacts_manager, DialogId dialog_id, bool is_bot) {
if (is_bot) {
return false;
}
switch (dialog_id.get_type()) {
case DialogType::User:
return !contacts_manager->is_user_bot(dialog_id.get_user_id());
case DialogType::SecretChat: {
auto user_id = contacts_manager->get_secret_chat_user_id(dialog_id.get_secret_chat_id());
return !contacts_manager->is_user_bot(user_id);
}
case DialogType::Chat:
case DialogType::Channel:
case DialogType::None:
return false;
default:
UNREACHABLE();
return false;
}
}
} // namespace td } // namespace td

View File

@ -149,6 +149,12 @@ vector<MessageEntity> get_message_entities(vector<tl_object_ptr<secret_api::Mess
Status fix_formatted_text(string &text, vector<MessageEntity> &entities, bool allow_empty, bool skip_new_entities, Status fix_formatted_text(string &text, vector<MessageEntity> &entities, bool allow_empty, bool skip_new_entities,
bool skip_bot_commands, bool for_draft) TD_WARN_UNUSED_RESULT; bool skip_bot_commands, bool for_draft) TD_WARN_UNUSED_RESULT;
FormattedText get_message_text(const ContactsManager *contacts_manager, string message_text,
vector<tl_object_ptr<telegram_api::MessageEntity>> &&server_entities, int32 send_date,
const char *source);
void add_formatted_text_dependencies(Dependencies &dependencies, const FormattedText *text); void add_formatted_text_dependencies(Dependencies &dependencies, const FormattedText *text);
bool need_skip_bot_commands(const ContactsManager *contacts_manager, DialogId dialog_id, bool is_bot);
} // namespace td } // namespace td

View File

@ -21,6 +21,7 @@
#include <utility> #include <utility>
namespace td { namespace td {
// append only before Size // append only before Size
enum class SearchMessagesFilter : int32 { enum class SearchMessagesFilter : int32 {
Empty, Empty,
@ -166,4 +167,26 @@ std::shared_ptr<MessagesDbSyncSafeInterface> create_messages_db_sync(
std::shared_ptr<MessagesDbAsyncInterface> create_messages_db_async(std::shared_ptr<MessagesDbSyncSafeInterface> sync_db, std::shared_ptr<MessagesDbAsyncInterface> create_messages_db_async(std::shared_ptr<MessagesDbSyncSafeInterface> sync_db,
int32 scheduler_id); int32 scheduler_id);
inline constexpr size_t search_messages_filter_size() {
return static_cast<int32>(SearchMessagesFilter::Size) - 1;
}
inline int32 search_messages_filter_index(SearchMessagesFilter filter) {
CHECK(filter != SearchMessagesFilter::Empty);
return static_cast<int32>(filter) - 1;
}
inline int32 search_messages_filter_index_mask(SearchMessagesFilter filter) {
if (filter == SearchMessagesFilter::Empty) {
return 0;
}
return 1 << search_messages_filter_index(filter);
}
inline int32 search_calls_filter_index(SearchMessagesFilter filter) {
CHECK(filter == SearchMessagesFilter::Call || filter == SearchMessagesFilter::MissedCall);
return static_cast<int32>(filter) - static_cast<int32>(SearchMessagesFilter::Call);
}
} // namespace td } // namespace td

File diff suppressed because it is too large Load Diff

View File

@ -19,28 +19,21 @@
#include "td/db/binlog/BinlogEvent.h" #include "td/db/binlog/BinlogEvent.h"
#include "td/telegram/AccessRights.h" #include "td/telegram/AccessRights.h"
#include "td/telegram/CallDiscardReason.h"
#include "td/telegram/ChannelId.h" #include "td/telegram/ChannelId.h"
#include "td/telegram/ChatId.h"
#include "td/telegram/Contact.h"
#include "td/telegram/Dependencies.h" #include "td/telegram/Dependencies.h"
#include "td/telegram/DialogId.h" #include "td/telegram/DialogId.h"
#include "td/telegram/DialogParticipant.h" #include "td/telegram/DialogParticipant.h"
#include "td/telegram/DocumentsManager.h"
#include "td/telegram/files/FileId.h" #include "td/telegram/files/FileId.h"
#include "td/telegram/Game.h"
#include "td/telegram/Global.h" #include "td/telegram/Global.h"
#include "td/telegram/Location.h" #include "td/telegram/InputMessageText.h"
#include "td/telegram/MessageContent.h"
#include "td/telegram/MessageEntity.h" #include "td/telegram/MessageEntity.h"
#include "td/telegram/MessageId.h" #include "td/telegram/MessageId.h"
#include "td/telegram/MessagesDb.h" #include "td/telegram/MessagesDb.h"
#include "td/telegram/net/NetQuery.h" #include "td/telegram/net/NetQuery.h"
#include "td/telegram/Payments.h"
#include "td/telegram/Photo.h"
#include "td/telegram/ReplyMarkup.h" #include "td/telegram/ReplyMarkup.h"
#include "td/telegram/SecretChatId.h" #include "td/telegram/SecretChatId.h"
#include "td/telegram/SecretInputMedia.h" #include "td/telegram/SecretInputMedia.h"
#include "td/telegram/SecureValue.h"
#include "td/telegram/UserId.h" #include "td/telegram/UserId.h"
#include "td/telegram/WebPageId.h" #include "td/telegram/WebPageId.h"
@ -70,638 +63,6 @@ class Td;
class MultiSequenceDispatcher; class MultiSequenceDispatcher;
enum class MessageContentType : int32 {
None = -1,
Text,
Animation,
Audio,
Document,
Photo,
Sticker,
Video,
VoiceNote,
Contact,
Location,
Venue,
ChatCreate,
ChatChangeTitle,
ChatChangePhoto,
ChatDeletePhoto,
ChatDeleteHistory,
ChatAddUsers,
ChatJoinedByLink,
ChatDeleteUser,
ChatMigrateTo,
ChannelCreate,
ChannelMigrateFrom,
PinMessage,
Game,
GameScore,
ScreenshotTaken,
ChatSetTtl,
Unsupported,
Call,
Invoice,
PaymentSuccessful,
VideoNote,
ContactRegistered,
ExpiredPhoto,
ExpiredVideo,
LiveLocation,
CustomServiceAction,
WebsiteConnected,
PassportDataSent,
PassportDataReceived
};
StringBuilder &operator<<(StringBuilder &string_builder, MessageContentType content_type);
// Do not forget to update MessagesManager::update_message_content when one of the inheritors of this class changes
class MessageContent {
public:
MessageContent() = default;
MessageContent(const MessageContent &) = default;
MessageContent &operator=(const MessageContent &) = default;
MessageContent(MessageContent &&) = default;
MessageContent &operator=(MessageContent &&) = default;
virtual MessageContentType get_type() const = 0;
virtual ~MessageContent() = default;
};
class MessageText : public MessageContent {
public:
FormattedText text;
WebPageId web_page_id;
MessageText() = default;
MessageText(FormattedText text, WebPageId web_page_id) : text(std::move(text)), web_page_id(web_page_id) {
}
MessageContentType get_type() const override {
return MessageContentType::Text;
}
};
class MessageAnimation : public MessageContent {
public:
FileId file_id;
FormattedText caption;
MessageAnimation() = default;
MessageAnimation(FileId file_id, FormattedText &&caption) : file_id(file_id), caption(std::move(caption)) {
}
MessageContentType get_type() const override {
return MessageContentType::Animation;
}
};
class MessageAudio : public MessageContent {
public:
FileId file_id;
FormattedText caption;
MessageAudio() = default;
MessageAudio(FileId file_id, FormattedText &&caption) : file_id(file_id), caption(std::move(caption)) {
}
MessageContentType get_type() const override {
return MessageContentType::Audio;
}
};
class MessageDocument : public MessageContent {
public:
FileId file_id;
FormattedText caption;
MessageDocument() = default;
MessageDocument(FileId file_id, FormattedText &&caption) : file_id(file_id), caption(std::move(caption)) {
}
MessageContentType get_type() const override {
return MessageContentType::Document;
}
};
class MessagePhoto : public MessageContent {
public:
Photo photo;
FormattedText caption;
MessagePhoto() = default;
MessagePhoto(Photo &&photo, FormattedText &&caption) : photo(std::move(photo)), caption(std::move(caption)) {
}
MessageContentType get_type() const override {
return MessageContentType::Photo;
}
};
class MessageSticker : public MessageContent {
public:
FileId file_id;
MessageSticker() = default;
explicit MessageSticker(FileId file_id) : file_id(file_id) {
}
MessageContentType get_type() const override {
return MessageContentType::Sticker;
}
};
class MessageVideo : public MessageContent {
public:
FileId file_id;
FormattedText caption;
MessageVideo() = default;
MessageVideo(FileId file_id, FormattedText &&caption) : file_id(file_id), caption(std::move(caption)) {
}
MessageContentType get_type() const override {
return MessageContentType::Video;
}
};
class MessageVoiceNote : public MessageContent {
public:
FileId file_id;
FormattedText caption;
bool is_listened;
MessageVoiceNote() = default;
MessageVoiceNote(FileId file_id, FormattedText &&caption, bool is_listened)
: file_id(file_id), caption(std::move(caption)), is_listened(is_listened) {
}
MessageContentType get_type() const override {
return MessageContentType::VoiceNote;
}
};
class MessageContact : public MessageContent {
public:
Contact contact;
MessageContact() = default;
explicit MessageContact(Contact &&contact) : contact(std::move(contact)) {
}
MessageContentType get_type() const override {
return MessageContentType::Contact;
}
};
class MessageLocation : public MessageContent {
public:
Location location;
MessageLocation() = default;
explicit MessageLocation(Location &&location) : location(std::move(location)) {
}
MessageContentType get_type() const override {
return MessageContentType::Location;
}
};
class MessageVenue : public MessageContent {
public:
Venue venue;
MessageVenue() = default;
explicit MessageVenue(Venue &&venue) : venue(std::move(venue)) {
}
MessageContentType get_type() const override {
return MessageContentType::Venue;
}
};
class MessageChatCreate : public MessageContent {
public:
string title;
vector<UserId> participant_user_ids;
MessageChatCreate() = default;
MessageChatCreate(string &&title, vector<UserId> &&participant_user_ids)
: title(std::move(title)), participant_user_ids(std::move(participant_user_ids)) {
}
MessageContentType get_type() const override {
return MessageContentType::ChatCreate;
}
};
class MessageChatChangeTitle : public MessageContent {
public:
string title;
MessageChatChangeTitle() = default;
explicit MessageChatChangeTitle(string &&title) : title(std::move(title)) {
}
MessageContentType get_type() const override {
return MessageContentType::ChatChangeTitle;
}
};
class MessageChatChangePhoto : public MessageContent {
public:
Photo photo;
MessageChatChangePhoto() = default;
explicit MessageChatChangePhoto(Photo &&photo) : photo(std::move(photo)) {
}
MessageContentType get_type() const override {
return MessageContentType::ChatChangePhoto;
}
};
class MessageChatDeletePhoto : public MessageContent {
public:
MessageContentType get_type() const override {
return MessageContentType::ChatDeletePhoto;
}
};
class MessageChatDeleteHistory : public MessageContent {
public:
MessageContentType get_type() const override {
return MessageContentType::ChatDeleteHistory;
}
};
class MessageChatAddUsers : public MessageContent {
public:
vector<UserId> user_ids;
MessageChatAddUsers() = default;
explicit MessageChatAddUsers(vector<UserId> &&user_ids) : user_ids(std::move(user_ids)) {
}
MessageContentType get_type() const override {
return MessageContentType::ChatAddUsers;
}
};
class MessageChatJoinedByLink : public MessageContent {
public:
MessageContentType get_type() const override {
return MessageContentType::ChatJoinedByLink;
}
};
class MessageChatDeleteUser : public MessageContent {
public:
UserId user_id;
MessageChatDeleteUser() = default;
explicit MessageChatDeleteUser(UserId user_id) : user_id(user_id) {
}
MessageContentType get_type() const override {
return MessageContentType::ChatDeleteUser;
}
};
class MessageChatMigrateTo : public MessageContent {
public:
ChannelId migrated_to_channel_id;
MessageChatMigrateTo() = default;
explicit MessageChatMigrateTo(ChannelId migrated_to_channel_id) : migrated_to_channel_id(migrated_to_channel_id) {
}
MessageContentType get_type() const override {
return MessageContentType::ChatMigrateTo;
}
};
class MessageChannelCreate : public MessageContent {
public:
string title;
MessageChannelCreate() = default;
explicit MessageChannelCreate(string &&title) : title(std::move(title)) {
}
MessageContentType get_type() const override {
return MessageContentType::ChannelCreate;
}
};
class MessageChannelMigrateFrom : public MessageContent {
public:
string title;
ChatId migrated_from_chat_id;
MessageChannelMigrateFrom() = default;
MessageChannelMigrateFrom(string &&title, ChatId migrated_from_chat_id)
: title(std::move(title)), migrated_from_chat_id(migrated_from_chat_id) {
}
MessageContentType get_type() const override {
return MessageContentType::ChannelMigrateFrom;
}
};
class MessagePinMessage : public MessageContent {
public:
MessageId message_id;
MessagePinMessage() = default;
explicit MessagePinMessage(MessageId message_id) : message_id(message_id) {
}
MessageContentType get_type() const override {
return MessageContentType::PinMessage;
}
};
class MessageGame : public MessageContent {
public:
Game game;
MessageGame() = default;
explicit MessageGame(Game &&game) : game(std::move(game)) {
}
MessageContentType get_type() const override {
return MessageContentType::Game;
}
};
class MessageGameScore : public MessageContent {
public:
MessageId game_message_id;
int64 game_id;
int32 score;
MessageGameScore() = default;
MessageGameScore(MessageId game_message_id, int64 game_id, int32 score)
: game_message_id(game_message_id), game_id(game_id), score(score) {
}
MessageContentType get_type() const override {
return MessageContentType::GameScore;
}
};
class MessageScreenshotTaken : public MessageContent {
public:
MessageContentType get_type() const override {
return MessageContentType::ScreenshotTaken;
}
};
class MessageChatSetTtl : public MessageContent {
public:
int32 ttl;
MessageChatSetTtl() = default;
explicit MessageChatSetTtl(int32 ttl) : ttl(ttl) {
}
MessageContentType get_type() const override {
return MessageContentType::ChatSetTtl;
}
};
class MessageUnsupported
: public MessageContent { // TODO save a layer in which the message was received to
// automatically reget it if the layer changes
public:
MessageContentType get_type() const override {
return MessageContentType::Unsupported;
}
};
class MessageCall : public MessageContent {
public:
int64 call_id;
int32 duration;
CallDiscardReason discard_reason;
MessageCall() = default;
MessageCall(int64 call_id, int32 duration, CallDiscardReason discard_reason)
: call_id(call_id), duration(duration), discard_reason(discard_reason) {
}
MessageContentType get_type() const override {
return MessageContentType::Call;
}
};
class MessageInvoice : public MessageContent {
public:
string title;
string description;
Photo photo;
string start_parameter;
// InputMessageInvoice
Invoice invoice;
string payload;
string provider_token;
string provider_data;
// MessageInvoice
int64 total_amount = 0;
MessageId receipt_message_id;
MessageInvoice() = default;
MessageInvoice(string &&title, string &&description, Photo &&photo, string &&start_parameter, int64 total_amount,
string &&currency, bool is_test, bool need_shipping_address, MessageId receipt_message_id)
: title(std::move(title))
, description(std::move(description))
, photo(std::move(photo))
, start_parameter(std::move(start_parameter))
, invoice(std::move(currency), is_test, need_shipping_address)
, payload()
, provider_token()
, provider_data()
, total_amount(total_amount)
, receipt_message_id(receipt_message_id) {
}
MessageContentType get_type() const override {
return MessageContentType::Invoice;
}
};
class MessagePaymentSuccessful : public MessageContent {
public:
MessageId invoice_message_id;
string currency;
int64 total_amount = 0;
// bots only part
string invoice_payload;
string shipping_option_id;
unique_ptr<OrderInfo> order_info;
string telegram_payment_charge_id;
string provider_payment_charge_id;
MessagePaymentSuccessful() = default;
MessagePaymentSuccessful(MessageId invoice_message_id, string &&currency, int64 total_amount)
: invoice_message_id(invoice_message_id), currency(std::move(currency)), total_amount(total_amount) {
}
MessageContentType get_type() const override {
return MessageContentType::PaymentSuccessful;
}
};
class MessageVideoNote : public MessageContent {
public:
FileId file_id;
bool is_viewed = false;
MessageVideoNote() = default;
MessageVideoNote(FileId file_id, bool is_viewed) : file_id(file_id), is_viewed(is_viewed) {
}
MessageContentType get_type() const override {
return MessageContentType::VideoNote;
}
};
class MessageContactRegistered : public MessageContent {
public:
MessageContentType get_type() const override {
return MessageContentType::ContactRegistered;
}
};
class MessageExpiredPhoto : public MessageContent {
public:
MessageExpiredPhoto() = default;
MessageContentType get_type() const override {
return MessageContentType::ExpiredPhoto;
}
};
class MessageExpiredVideo : public MessageContent {
public:
MessageExpiredVideo() = default;
MessageContentType get_type() const override {
return MessageContentType::ExpiredVideo;
}
};
class MessageLiveLocation : public MessageContent {
public:
Location location;
int32 period;
MessageLiveLocation() = default;
MessageLiveLocation(Location &&location, int32 period) : location(std::move(location)), period(period) {
}
MessageContentType get_type() const override {
return MessageContentType::LiveLocation;
}
};
class MessageCustomServiceAction : public MessageContent {
public:
string message;
MessageCustomServiceAction() = default;
explicit MessageCustomServiceAction(string &&message) : message(std::move(message)) {
}
MessageContentType get_type() const override {
return MessageContentType::CustomServiceAction;
}
};
class MessageWebsiteConnected : public MessageContent {
public:
string domain_name;
MessageWebsiteConnected() = default;
explicit MessageWebsiteConnected(string &&domain_name) : domain_name(std::move(domain_name)) {
}
MessageContentType get_type() const override {
return MessageContentType::WebsiteConnected;
}
};
class MessagePassportDataSent : public MessageContent {
public:
vector<SecureValueType> types;
MessagePassportDataSent() = default;
explicit MessagePassportDataSent(vector<SecureValueType> &&types) : types(std::move(types)) {
}
MessageContentType get_type() const override {
return MessageContentType::PassportDataSent;
}
};
class MessagePassportDataReceived : public MessageContent {
public:
vector<EncryptedSecureValue> values;
EncryptedSecureCredentials credentials;
MessagePassportDataReceived() = default;
MessagePassportDataReceived(vector<EncryptedSecureValue> &&values, EncryptedSecureCredentials &&credentials)
: values(std::move(values)), credentials(std::move(credentials)) {
}
MessageContentType get_type() const override {
return MessageContentType::PassportDataReceived;
}
};
struct InputMessageContent {
unique_ptr<MessageContent> content;
bool disable_web_page_preview = false;
bool clear_draft = false;
int32 ttl = 0;
UserId via_bot_user_id;
InputMessageContent(unique_ptr<MessageContent> &&content, bool disable_web_page_preview, bool clear_draft, int32 ttl,
UserId via_bot_user_id)
: content(std::move(content))
, disable_web_page_preview(disable_web_page_preview)
, clear_draft(clear_draft)
, ttl(ttl)
, via_bot_user_id(via_bot_user_id) {
}
};
class InputMessageText {
public:
FormattedText text;
bool disable_web_page_preview = false;
bool clear_draft = false;
InputMessageText() = default;
InputMessageText(FormattedText text, bool disable_web_page_preview, bool clear_draft)
: text(std::move(text)), disable_web_page_preview(disable_web_page_preview), clear_draft(clear_draft) {
}
};
bool operator==(const InputMessageText &lhs, const InputMessageText &rhs);
bool operator!=(const InputMessageText &lhs, const InputMessageText &rhs);
class DraftMessage { class DraftMessage {
public: public:
int32 date; int32 date;
@ -778,27 +139,6 @@ inline StringBuilder &operator<<(StringBuilder &string_builder, ScopeNotificatio
<< notification_settings.show_preview << ", " << notification_settings.is_synchronized << "]"; << notification_settings.show_preview << ", " << notification_settings.is_synchronized << "]";
} }
inline constexpr size_t search_messages_filter_size() {
return static_cast<int32>(SearchMessagesFilter::Size) - 1;
}
inline int32 search_messages_filter_index(SearchMessagesFilter filter) {
CHECK(filter != SearchMessagesFilter::Empty);
return static_cast<int32>(filter) - 1;
}
inline int32 search_messages_filter_index_mask(SearchMessagesFilter filter) {
if (filter == SearchMessagesFilter::Empty) {
return 0;
}
return 1 << search_messages_filter_index(filter);
}
inline int32 search_calls_filter_index(SearchMessagesFilter filter) {
CHECK(filter == SearchMessagesFilter::Call || filter == SearchMessagesFilter::MissedCall);
return static_cast<int32>(filter) - static_cast<int32>(SearchMessagesFilter::Call);
}
class DialogDate { class DialogDate {
int64 order; int64 order;
DialogId dialog_id; DialogId dialog_id;
@ -1079,30 +419,6 @@ class MessagesManager : public Actor {
tl_object_ptr<td_api::InputMessageContent> &input_message_content, tl_object_ptr<td_api::InputMessageContent> &input_message_content,
bool is_bot) const; bool is_bot) const;
static Result<InputMessageText> process_input_message_text(
const ContactsManager *contacts_manager, DialogId dialog_id,
tl_object_ptr<td_api::InputMessageContent> &&input_message_content, bool is_bot,
bool for_draft = false) TD_WARN_UNUSED_RESULT;
static Result<std::pair<Location, int32>> process_input_message_location(
tl_object_ptr<td_api::InputMessageContent> &&input_message_content) TD_WARN_UNUSED_RESULT;
static Result<Venue> process_input_message_venue(tl_object_ptr<td_api::InputMessageContent> &&input_message_content)
TD_WARN_UNUSED_RESULT;
static Result<Contact> process_input_message_contact(
tl_object_ptr<td_api::InputMessageContent> &&input_message_content) TD_WARN_UNUSED_RESULT;
static Result<Game> process_input_message_game(const ContactsManager *contacts_manager,
tl_object_ptr<td_api::InputMessageContent> &&input_message_content)
TD_WARN_UNUSED_RESULT;
static bool need_skip_bot_commands(const ContactsManager *contacts_manager, DialogId dialog_id, bool is_bot);
static FormattedText get_message_text(const ContactsManager *contacts_manager, string message_text,
vector<tl_object_ptr<telegram_api::MessageEntity>> &&server_entities,
int32 send_date, const char *source);
Result<MessageId> send_message(DialogId dialog_id, MessageId reply_to_message_id, bool disable_notification, Result<MessageId> send_message(DialogId dialog_id, MessageId reply_to_message_id, bool disable_notification,
bool from_background, tl_object_ptr<td_api::ReplyMarkup> &&reply_markup, bool from_background, tl_object_ptr<td_api::ReplyMarkup> &&reply_markup,
tl_object_ptr<td_api::InputMessageContent> &&input_message_content) tl_object_ptr<td_api::InputMessageContent> &&input_message_content)
@ -1948,9 +1264,6 @@ class MessagesManager : public Actor {
static constexpr int32 USERNAME_CACHE_EXPIRE_TIME = 3 * 86400; static constexpr int32 USERNAME_CACHE_EXPIRE_TIME = 3 * 86400;
static constexpr int32 USERNAME_CACHE_EXPIRE_TIME_SHORT = 900; static constexpr int32 USERNAME_CACHE_EXPIRE_TIME_SHORT = 900;
static constexpr int32 MIN_LIVE_LOCATION_PERIOD = 60; // seconds, server side limit
static constexpr int32 MAX_LIVE_LOCATION_PERIOD = 86400; // seconds, server side limit
static constexpr int32 MAX_RESEND_DELAY = 86400; // seconds, some resonable limit static constexpr int32 MAX_RESEND_DELAY = 86400; // seconds, some resonable limit
static constexpr int32 MAX_PRELOADED_DIALOGS = 1000; static constexpr int32 MAX_PRELOADED_DIALOGS = 1000;
@ -1984,16 +1297,9 @@ class MessagesManager : public Actor {
FullMessageId on_get_message(MessageInfo &&message_info, bool from_update, bool is_channel_message, FullMessageId on_get_message(MessageInfo &&message_info, bool from_update, bool is_channel_message,
bool have_previous, bool have_next, const char *source); bool have_previous, bool have_next, const char *source);
static unique_ptr<MessageContent> create_text_message_content(string text, vector<MessageEntity> entities,
WebPageId web_page_id);
Result<InputMessageContent> process_input_message_content( Result<InputMessageContent> process_input_message_content(
DialogId dialog_id, tl_object_ptr<td_api::InputMessageContent> &&input_message_content) const; DialogId dialog_id, tl_object_ptr<td_api::InputMessageContent> &&input_message_content) const;
static Result<InputMessageContent> create_input_message_content(
DialogId dialog_id, tl_object_ptr<td_api::InputMessageContent> &&input_message_content, Td *td,
FormattedText caption, FileId file_id, PhotoSize thumbnail, vector<FileId> sticker_file_ids);
Message *get_message_to_send(Dialog *d, MessageId reply_to_message_id, bool disable_notification, Message *get_message_to_send(Dialog *d, MessageId reply_to_message_id, bool disable_notification,
bool from_background, unique_ptr<MessageContent> &&content, bool *need_update_dialog_pos, bool from_background, unique_ptr<MessageContent> &&content, bool *need_update_dialog_pos,
unique_ptr<MessageForwardInfo> forward_info = nullptr); unique_ptr<MessageForwardInfo> forward_info = nullptr);
@ -2041,25 +1347,6 @@ class MessagesManager : public Actor {
bool disable_notification, bool from_background, bool disable_notification, bool from_background,
bool in_game_share) TD_WARN_UNUSED_RESULT; bool in_game_share) TD_WARN_UNUSED_RESULT;
static SecretInputMedia get_secret_input_media(const MessageContent *content, Td *td,
tl_object_ptr<telegram_api::InputEncryptedFile> input_file,
BufferSlice thumbnail, int32 layer);
static tl_object_ptr<telegram_api::invoice> get_input_invoice(const Invoice &invoice);
static tl_object_ptr<telegram_api::inputWebDocument> get_input_web_document(const FileManager *file_manager,
const Photo &photo);
static tl_object_ptr<telegram_api::inputMediaInvoice> get_input_media_invoice(const FileManager *file_manager,
const MessageInvoice *message_invoice);
static tl_object_ptr<telegram_api::InputMedia> get_input_media(const MessageContent *content, Td *td,
tl_object_ptr<telegram_api::InputFile> input_file,
tl_object_ptr<telegram_api::InputFile> input_thumbnail,
int32 ttl);
static void delete_message_content_thumbnail(MessageContent *content, Td *td);
void do_send_media(DialogId dialog_id, Message *m, FileId file_id, FileId thumbnail_file_id, void do_send_media(DialogId dialog_id, Message *m, FileId file_id, FileId thumbnail_file_id,
tl_object_ptr<telegram_api::InputFile> input_file, tl_object_ptr<telegram_api::InputFile> input_file,
tl_object_ptr<telegram_api::InputFile> input_thumbnail); tl_object_ptr<telegram_api::InputFile> input_thumbnail);
@ -2104,18 +1391,8 @@ class MessagesManager : public Actor {
bool is_message_unload_enabled() const; bool is_message_unload_enabled() const;
static bool is_allowed_media_group_content(MessageContentType content_type);
static bool can_forward_message(DialogId from_dialog_id, const Message *m); static bool can_forward_message(DialogId from_dialog_id, const Message *m);
static bool can_forward_message_content(const MessageContent *content);
static bool is_secret_message_content(int32 ttl, MessageContentType content_type);
static bool is_service_message_content(MessageContentType content_type);
static bool can_have_message_content_caption(MessageContentType content_type);
static bool can_delete_channel_message(DialogParticipantStatus status, const Message *m, bool is_bot); static bool can_delete_channel_message(DialogParticipantStatus status, const Message *m, bool is_bot);
bool can_revoke_message(DialogId dialog_id, const Message *m) const; bool can_revoke_message(DialogId dialog_id, const Message *m) const;
@ -2162,8 +1439,6 @@ class MessagesManager : public Actor {
bool update_message_contains_unread_mention(Dialog *d, Message *m, bool contains_unread_mention, const char *source); bool update_message_contains_unread_mention(Dialog *d, Message *m, bool contains_unread_mention, const char *source);
static bool update_opened_message_content(MessageContent *content);
void read_message_content_from_updates(MessageId message_id); void read_message_content_from_updates(MessageId message_id);
void read_channel_message_content_from_updates(Dialog *d, MessageId message_id); void read_channel_message_content_from_updates(Dialog *d, MessageId message_id);
@ -2246,15 +1521,6 @@ class MessagesManager : public Actor {
int32 get_message_index_mask(DialogId dialog_id, const Message *m) const; int32 get_message_index_mask(DialogId dialog_id, const Message *m) const;
static int32 get_message_content_index_mask(const MessageContent *content, const Td *td, bool is_secret,
bool is_outgoing);
static int32 get_message_content_new_participant_count(const MessageContent *content);
static MessageId get_message_content_pinned_message_id(const MessageContent *content);
static UserId get_message_content_deleted_user_id(const MessageContent *content);
Message *add_message_to_dialog(DialogId dialog_id, unique_ptr<Message> message, bool from_update, bool *need_update, Message *add_message_to_dialog(DialogId dialog_id, unique_ptr<Message> message, bool from_update, bool *need_update,
bool *need_update_dialog_pos, const char *source); bool *need_update_dialog_pos, const char *source);
@ -2281,20 +1547,7 @@ class MessagesManager : public Actor {
void update_message(Dialog *d, unique_ptr<Message> &old_message, unique_ptr<Message> new_message, void update_message(Dialog *d, unique_ptr<Message> &old_message, unique_ptr<Message> new_message,
bool need_send_update_message_content, bool *need_update_dialog_pos); bool need_send_update_message_content, bool *need_update_dialog_pos);
static WebPageId get_message_content_web_page_id(const MessageContent *content); static bool need_message_changed_warning(const Message *old_message);
static void set_message_content_web_page_id(MessageContent *content, WebPageId web_page_id);
static bool need_message_text_changed_warning(const Message *old_message, const MessageText *old_content,
const MessageText *new_content);
static void merge_location_access_hash(Location &first, Location &second);
static void merge_message_contents(Td *td, const Message *old_message, MessageContent *old_content,
MessageContent *new_content, DialogId dialog_id, bool need_merge_files,
bool &is_content_changed, bool &need_update);
static bool merge_message_content_file_id(Td *td, MessageContent *message_content, FileId new_file_id);
bool update_message_content(DialogId dialog_id, Message *old_message, unique_ptr<MessageContent> new_content, bool update_message_content(DialogId dialog_id, Message *old_message, unique_ptr<MessageContent> new_content,
bool need_send_update_message_content, bool need_merge_files); bool need_send_update_message_content, bool need_merge_files);
@ -2422,9 +1675,6 @@ class MessagesManager : public Actor {
void add_dialog_last_database_message(Dialog *d, unique_ptr<Message> &&last_database_message); void add_dialog_last_database_message(Dialog *d, unique_ptr<Message> &&last_database_message);
tl_object_ptr<td_api::inputMessageText> get_input_message_text_object(
const InputMessageText &input_message_text) const;
tl_object_ptr<td_api::draftMessage> get_draft_message_object(const unique_ptr<DraftMessage> &draft_message) const; tl_object_ptr<td_api::draftMessage> get_draft_message_object(const unique_ptr<DraftMessage> &draft_message) const;
tl_object_ptr<td_api::ChatType> get_chat_type_object(DialogId dialog_id) const; tl_object_ptr<td_api::ChatType> get_chat_type_object(DialogId dialog_id) const;
@ -2501,56 +1751,6 @@ class MessagesManager : public Actor {
static unique_ptr<DraftMessage> get_draft_message(ContactsManager *contacts_manager, static unique_ptr<DraftMessage> get_draft_message(ContactsManager *contacts_manager,
tl_object_ptr<telegram_api::DraftMessage> &&draft_message_ptr); tl_object_ptr<telegram_api::DraftMessage> &&draft_message_ptr);
static FormattedText get_secret_media_caption(string &&message_text, string &&message_caption);
static unique_ptr<MessageContent> get_secret_document_message_content(
Td *td, tl_object_ptr<telegram_api::encryptedFile> file,
tl_object_ptr<secret_api::decryptedMessageMediaDocument> &&document,
vector<tl_object_ptr<telegram_api::DocumentAttribute>> &&attributes, DialogId owner_dialog_id,
FormattedText &&caption, bool is_opened);
static unique_ptr<MessageContent> get_document_message_content(Td *td,
tl_object_ptr<telegram_api::document> &&document,
DialogId owner_dialog_id, FormattedText &&caption,
bool is_opened,
MultiPromiseActor *load_data_multipromise_ptr);
static unique_ptr<MessageContent> get_document_message_content(
std::pair<DocumentsManager::DocumentType, FileId> &&parsed_document, FormattedText &&caption, bool is_opened);
static unique_ptr<MessageContent> get_secret_message_content(
Td *td, string message_text, tl_object_ptr<telegram_api::encryptedFile> file,
tl_object_ptr<secret_api::DecryptedMessageMedia> &&media,
vector<tl_object_ptr<secret_api::MessageEntity>> &&secret_entities, DialogId owner_dialog_id,
MultiPromiseActor &load_data_multipromise);
static unique_ptr<MessageContent> get_message_content(Td *td, FormattedText message_text,
tl_object_ptr<telegram_api::MessageMedia> &&media,
DialogId owner_dialog_id, bool is_content_read,
UserId via_bot_user_id, int32 *ttl);
static unique_ptr<MessageContent> dup_message_content(Td *td, DialogId dialog_id, const MessageContent *content,
bool for_forward);
static unique_ptr<MessageContent> get_action_message_content(Td *td,
tl_object_ptr<telegram_api::MessageAction> &&action,
DialogId owner_dialog_id, MessageId reply_to_message_id);
static tl_object_ptr<td_api::MessageContent> get_message_content_object(const MessageContent *content, Td *td,
int32 message_date, bool is_content_secret);
static const FormattedText *get_message_content_text(const MessageContent *content);
static const FormattedText *get_message_content_caption(const MessageContent *content);
static int32 get_message_content_duration(const MessageContent *content, const Td *td);
static FileId get_message_content_file_id(const MessageContent *content);
static void update_message_content_file_id_remote(MessageContent *content, FileId file_id);
static FileId get_message_content_thumbnail_file_id(const MessageContent *content, const Td *td);
vector<FileId> get_message_file_ids(const Message *message) const; vector<FileId> get_message_file_ids(const Message *message) const;
void cancel_upload_message_content_files(const MessageContent *content); void cancel_upload_message_content_files(const MessageContent *content);
@ -2743,8 +1943,6 @@ class MessagesManager : public Actor {
string get_search_text(const Message *m) const; string get_search_text(const Message *m) const;
static string get_message_content_search_text(const Td *td, const MessageContent *content);
unique_ptr<Dialog> parse_dialog(DialogId dialog_id, const BufferSlice &value); unique_ptr<Dialog> parse_dialog(DialogId dialog_id, const BufferSlice &value);
void load_calls_db_state(); void load_calls_db_state();
@ -2756,8 +1954,6 @@ class MessagesManager : public Actor {
static void dump_debug_message_op(const Dialog *d, int priority = 0); static void dump_debug_message_op(const Dialog *d, int priority = 0);
static void add_message_content_dependencies(Dependencies &dependencies, const MessageContent *message_content);
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);
static void add_dialog_dependencies(Dependencies &dependencies, DialogId dialog_id); static void add_dialog_dependencies(Dependencies &dependencies, DialogId dialog_id);

View File

@ -44,6 +44,7 @@
#include "td/telegram/MessagesManager.h" #include "td/telegram/MessagesManager.h"
#include "td/telegram/misc.h" #include "td/telegram/misc.h"
#include "td/telegram/PasswordManager.h" #include "td/telegram/PasswordManager.h"
#include "td/telegram/Payments.h"
#include "td/telegram/Photo.h" #include "td/telegram/Photo.h"
#include "td/telegram/PrivacyManager.h" #include "td/telegram/PrivacyManager.h"
#include "td/telegram/SecretChatId.h" #include "td/telegram/SecretChatId.h"