diff --git a/td/generate/scheme/td_api.tl b/td/generate/scheme/td_api.tl index 40f6ad17d..160e077d4 100644 --- a/td/generate/scheme/td_api.tl +++ b/td/generate/scheme/td_api.tl @@ -3423,6 +3423,9 @@ storyAreaTypeVenue venue:venue = StoryAreaType; //@is_flipped True, if reaction corner is flipped storyAreaTypeSuggestedReaction reaction_type:ReactionType total_count:int32 is_dark:Bool is_flipped:Bool = StoryAreaType; +//@description An area pointing to a message @chat_id Identifier of the chat with the message @message_id Identifier of the message +storyAreaTypeMessage chat_id:int53 message_id:int53 = StoryAreaType; + //@description Describes a clickable rectangle area on a story media @position Position of the area @type Type of the area storyArea position:storyAreaPosition type:StoryAreaType = StoryArea; @@ -3449,6 +3452,11 @@ inputStoryAreaTypePreviousVenue venue_provider:string venue_id:string = InputSto //@is_flipped True, if reaction corner is flipped inputStoryAreaTypeSuggestedReaction reaction_type:ReactionType is_dark:Bool is_flipped:Bool = InputStoryAreaType; +//@description An area pointing to a message +//@chat_id Identifier of the chat with the message. Currently, the chat must be a supergroup or a channel chat +//@message_id Identifier of the message. Only successfully sent non-scheduled messages can be specified +inputStoryAreaTypeMessage chat_id:int53 message_id:int53 = InputStoryAreaType; + //@description Describes a clickable rectangle area on a story media to be added @position Position of the area @type Type of the area inputStoryArea position:storyAreaPosition type:InputStoryAreaType = InputStoryArea; diff --git a/td/telegram/MediaArea.cpp b/td/telegram/MediaArea.cpp index 1b4de3616..c18e471a7 100644 --- a/td/telegram/MediaArea.cpp +++ b/td/telegram/MediaArea.cpp @@ -6,7 +6,10 @@ // #include "td/telegram/MediaArea.h" +#include "td/telegram/ContactsManager.h" +#include "td/telegram/Dependencies.h" #include "td/telegram/InlineQueriesManager.h" +#include "td/telegram/MessagesManager.h" #include "td/telegram/Td.h" #include "td/utils/logging.h" @@ -52,8 +55,19 @@ MediaArea::MediaArea(Td *td, telegram_api::object_ptr & } break; } - case telegram_api::mediaAreaChannelPost::ID: + case telegram_api::mediaAreaChannelPost::ID: { + auto area = telegram_api::move_object_as(media_area_ptr); + coordinates_ = MediaAreaCoordinates(area->coordinates_); + auto channel_id = ChannelId(area->channel_id_); + auto server_message_id = ServerMessageId(area->msg_id_); + if (coordinates_.is_valid() && channel_id.is_valid() && server_message_id.is_valid()) { + type_ = Type::Venue; + message_full_id_ = MessageFullId(DialogId(channel_id), MessageId(server_message_id)); + } else { + LOG(ERROR) << "Receive " << to_string(area); + } break; + } case telegram_api::inputMediaAreaVenue::ID: LOG(ERROR) << "Receive " << to_string(media_area_ptr); break; @@ -124,6 +138,30 @@ MediaArea::MediaArea(Td *td, td_api::object_ptr &&input_ } break; } + case td_api::inputStoryAreaTypeMessage::ID: { + auto type = td_api::move_object_as(input_story_area->type_); + auto dialog_id = DialogId(type->chat_id_); + auto message_id = MessageId(type->message_id_); + auto message_full_id = MessageFullId(dialog_id, message_id); + for (auto &old_media_area : old_media_areas) { + if (old_media_area.type_ == Type::Message && old_media_area.message_full_id_ == message_full_id) { + message_full_id_ = message_full_id; + is_old_message_ = true; + type_ = Type::Message; + break; + } + } + if (!is_old_message_) { + if (dialog_id.get_type() != DialogType::Channel || + !td->messages_manager_->have_message_force(message_full_id, "inputStoryAreaTypeMessage") || + !message_id.is_valid() || !message_id.is_server()) { + break; + } + message_full_id_ = message_full_id; + type_ = Type::Message; + } + break; + } default: UNREACHABLE(); } @@ -134,7 +172,7 @@ bool MediaArea::has_reaction_type(const ReactionType &reaction_type) const { } td_api::object_ptr MediaArea::get_story_area_object( - const vector> &reaction_counts) const { + Td *td, const vector> &reaction_counts) const { CHECK(is_valid()); td_api::object_ptr type; switch (type_) { @@ -155,13 +193,18 @@ td_api::object_ptr MediaArea::get_story_area_object( total_count, is_dark_, is_flipped_); break; } + case Type::Message: + type = td_api::make_object( + td->messages_manager_->get_chat_id_object(message_full_id_.get_dialog_id(), "storyAreaTypeMessage"), + message_full_id_.get_message_id().get()); + break; default: UNREACHABLE(); } return td_api::make_object(coordinates_.get_story_area_position_object(), std::move(type)); } -telegram_api::object_ptr MediaArea::get_input_media_area() const { +telegram_api::object_ptr MediaArea::get_input_media_area(const Td *td) const { CHECK(is_valid()); switch (type_) { case Type::Location: @@ -185,6 +228,21 @@ telegram_api::object_ptr MediaArea::get_input_media_are flags, false /*ignored*/, false /*ignored*/, coordinates_.get_input_media_area_coordinates(), reaction_type_.get_input_reaction()); } + case Type::Message: + if (!is_old_message_) { + auto input_channel = + td->contacts_manager_->get_input_channel(message_full_id_.get_dialog_id().get_channel_id()); + if (input_channel == nullptr) { + return nullptr; + } + return telegram_api::make_object( + coordinates_.get_input_media_area_coordinates(), std::move(input_channel), + message_full_id_.get_message_id().get_server_message_id().get()); + } + return telegram_api::make_object( + coordinates_.get_input_media_area_coordinates(), + message_full_id_.get_message_id().get_server_message_id().get(), + message_full_id_.get_message_id().get_server_message_id().get()); default: UNREACHABLE(); return nullptr; @@ -192,10 +250,10 @@ telegram_api::object_ptr MediaArea::get_input_media_are } vector> MediaArea::get_input_media_areas( - const vector &media_areas) { + const Td *td, const vector &media_areas) { vector> input_media_areas; for (const auto &media_area : media_areas) { - auto input_media_area = media_area.get_input_media_area(); + auto input_media_area = media_area.get_input_media_area(td); if (input_media_area != nullptr) { input_media_areas.push_back(std::move(input_media_area)); } @@ -203,11 +261,16 @@ vector> MediaArea::get_input_m return input_media_areas; } +void MediaArea::add_dependencies(Dependencies &dependencies) const { + dependencies.add_dialog_and_dependencies(message_full_id_.get_dialog_id()); +} + bool operator==(const MediaArea &lhs, const MediaArea &rhs) { return lhs.type_ == rhs.type_ && lhs.coordinates_ == rhs.coordinates_ && lhs.location_ == rhs.location_ && - lhs.venue_ == rhs.venue_ && lhs.input_query_id_ == rhs.input_query_id_ && - lhs.input_result_id_ == rhs.input_result_id_ && lhs.reaction_type_ == rhs.reaction_type_ && - lhs.is_dark_ == rhs.is_dark_ && lhs.is_flipped_ == rhs.is_flipped_; + lhs.venue_ == rhs.venue_ && lhs.message_full_id_ == rhs.message_full_id_ && + lhs.input_query_id_ == rhs.input_query_id_ && lhs.input_result_id_ == rhs.input_result_id_ && + lhs.reaction_type_ == rhs.reaction_type_ && lhs.is_dark_ == rhs.is_dark_ && + lhs.is_flipped_ == rhs.is_flipped_ && lhs.is_old_message_ == rhs.is_old_message_; } bool operator!=(const MediaArea &lhs, const MediaArea &rhs) { @@ -216,7 +279,8 @@ bool operator!=(const MediaArea &lhs, const MediaArea &rhs) { StringBuilder &operator<<(StringBuilder &string_builder, const MediaArea &media_area) { return string_builder << "StoryArea[" << media_area.coordinates_ << ": " << media_area.location_ << '/' - << media_area.venue_ << '/' << media_area.reaction_type_ << ']'; + << media_area.venue_ << '/' << media_area.reaction_type_ << '/' << media_area.message_full_id_ + << ']'; } } // namespace td diff --git a/td/telegram/MediaArea.h b/td/telegram/MediaArea.h index b654c25da..fd77666ca 100644 --- a/td/telegram/MediaArea.h +++ b/td/telegram/MediaArea.h @@ -8,6 +8,7 @@ #include "td/telegram/Location.h" #include "td/telegram/MediaAreaCoordinates.h" +#include "td/telegram/MessageFullId.h" #include "td/telegram/ReactionType.h" #include "td/telegram/td_api.h" #include "td/telegram/telegram_api.h" @@ -20,26 +21,29 @@ namespace td { +class Dependencies; class Td; class MediaArea { - enum class Type : int32 { None, Location, Venue, Reaction }; + enum class Type : int32 { None, Location, Venue, Reaction, Message }; Type type_ = Type::None; MediaAreaCoordinates coordinates_; Location location_; Venue venue_; + MessageFullId message_full_id_; int64 input_query_id_ = 0; string input_result_id_; ReactionType reaction_type_; bool is_dark_ = false; bool is_flipped_ = false; + bool is_old_message_ = false; friend bool operator==(const MediaArea &lhs, const MediaArea &rhs); friend bool operator!=(const MediaArea &lhs, const MediaArea &rhs); friend StringBuilder &operator<<(StringBuilder &string_builder, const MediaArea &media_area); - telegram_api::object_ptr get_input_media_area() const; + telegram_api::object_ptr get_input_media_area(const Td *td) const; public: MediaArea() = default; @@ -52,15 +56,17 @@ class MediaArea { bool has_reaction_type(const ReactionType &reaction_type) const; td_api::object_ptr get_story_area_object( - const vector> &reaction_counts) const; + Td *td, const vector> &reaction_counts) const; static vector> get_input_media_areas( - const vector &media_areas); + const Td *td, const vector &media_areas); bool is_valid() const { return type_ != Type::None; } + void add_dependencies(Dependencies &dependencies) const; + template void store(StorerT &storer) const; diff --git a/td/telegram/MediaArea.hpp b/td/telegram/MediaArea.hpp index 6096cb4ab..bd6ccea71 100644 --- a/td/telegram/MediaArea.hpp +++ b/td/telegram/MediaArea.hpp @@ -21,6 +21,7 @@ void MediaArea::store(StorerT &storer) const { STORE_FLAG(has_input_query_id); STORE_FLAG(is_dark_); STORE_FLAG(is_flipped_); + STORE_FLAG(is_old_message_); END_STORE_FLAGS(); store(type_, storer); store(coordinates_, storer); @@ -38,6 +39,9 @@ void MediaArea::store(StorerT &storer) const { case Type::Reaction: store(reaction_type_, storer); break; + case Type::Message: + store(message_full_id_, storer); + break; default: UNREACHABLE(); } @@ -51,6 +55,7 @@ void MediaArea::parse(ParserT &parser) { PARSE_FLAG(has_input_query_id); PARSE_FLAG(is_dark_); PARSE_FLAG(is_flipped_); + PARSE_FLAG(is_old_message_); END_PARSE_FLAGS(); parse(type_, parser); parse(coordinates_, parser); @@ -68,6 +73,9 @@ void MediaArea::parse(ParserT &parser) { case Type::Reaction: parse(reaction_type_, parser); break; + case Type::Message: + parse(message_full_id_, parser); + break; default: parser.set_error("Load invalid area type"); } diff --git a/td/telegram/StoryManager.cpp b/td/telegram/StoryManager.cpp index 637f77ce0..a52143fc4 100644 --- a/td/telegram/StoryManager.cpp +++ b/td/telegram/StoryManager.cpp @@ -888,7 +888,7 @@ class StoryManager::SendStoryQuery final : public Td::ResultHandler { if (story->noforwards_) { flags |= telegram_api::stories_sendStory::NOFORWARDS_MASK; } - auto input_media_areas = MediaArea::get_input_media_areas(story->areas_); + auto input_media_areas = MediaArea::get_input_media_areas(td_, story->areas_); if (!input_media_areas.empty()) { flags |= telegram_api::stories_sendStory::MEDIA_AREAS_MASK; } @@ -965,9 +965,9 @@ class StoryManager::EditStoryQuery final : public Td::ResultHandler { } vector> input_media_areas; if (edited_story->edit_media_areas_) { - input_media_areas = MediaArea::get_input_media_areas(edited_story->areas_); + input_media_areas = MediaArea::get_input_media_areas(td_, edited_story->areas_); } else if (content != nullptr) { - input_media_areas = MediaArea::get_input_media_areas(story->areas_); + input_media_areas = MediaArea::get_input_media_areas(td_, story->areas_); } if (!input_media_areas.empty()) { flags |= telegram_api::stories_editStory::MEDIA_AREAS_MASK; @@ -1844,6 +1844,9 @@ void StoryManager::add_story_dependencies(Dependencies &dependencies, const Stor add_story_content_dependencies(dependencies, story->content_.get()); } add_formatted_text_dependencies(dependencies, &story->caption_); + for (const auto &media_area : story->areas_) { + media_area.add_dependencies(dependencies); + } } void StoryManager::add_pending_story_dependencies(Dependencies &dependencies, const PendingStory *pending_story) { @@ -3046,8 +3049,8 @@ td_api::object_ptr StoryManager::get_story_object(StoryFullId sto unix_time >= get_story_viewers_expire_date(story) && interaction_info != nullptr && interaction_info->view_count_ > interaction_info->reaction_count_; const auto &reaction_counts = story->interaction_info_.get_reaction_counts(); - auto story_areas = transform(*areas, [&reaction_counts](const MediaArea &media_area) { - return media_area.get_story_area_object(reaction_counts); + auto story_areas = transform(*areas, [td = td_, &reaction_counts](const MediaArea &media_area) { + return media_area.get_story_area_object(td, reaction_counts); }); story->is_update_sent_ = true; diff --git a/td/telegram/cli.cpp b/td/telegram/cli.cpp index ecac5d13c..8ec799f9c 100644 --- a/td/telegram/cli.cpp +++ b/td/telegram/cli.cpp @@ -1297,6 +1297,12 @@ class CliClient final : public Actor { } else if (area[0] == 'r') { type = td_api::make_object(as_reaction_type(area.substr(1)), rand_bool(), rand_bool()); + } else if (area[0] == 'm') { + string chat_id; + string message_id; + std::tie(chat_id, message_id) = split(area.substr(1), ':'); + type = td_api::make_object(to_integer(chat_id), + as_message_id(message_id)); } result->areas_.push_back(td_api::make_object(std::move(position), std::move(type))); }