diff --git a/td/generate/scheme/td_api.tl b/td/generate/scheme/td_api.tl index 300d1d816..1bba38458 100644 --- a/td/generate/scheme/td_api.tl +++ b/td/generate/scheme/td_api.tl @@ -250,7 +250,7 @@ minithumbnail width:int32 height:int32 data:bytes = Minithumbnail; //@description The thumbnail is in JPEG format thumbnailFormatJpeg = ThumbnailFormat; -//@description The thumbnail is in static GIF format. It will be used only for some bot inline results +//@description The thumbnail is in static GIF format. It will be used only for some bot inline query results thumbnailFormatGif = ThumbnailFormat; //@description The thumbnail is in MPEG4 format. It will be used only for some animations and videos @@ -4929,6 +4929,26 @@ storyAreaTypeVenue venue:venue = StoryAreaType; storyArea position:storyAreaPosition type:StoryAreaType = StoryArea; +//@class InputStoryAreaType @description Describes type of a clickable rectangle area on a story media to be added + +//@description An area pointing to a location @location The location +inputStoryAreaTypeLocation location:location = InputStoryAreaType; + +//@description An area pointing to a venue found by the bot GetOption("venue_search_bot_username") +//@query_id Identifier of the inline query, used to found the venue +//@result_id Identifier of the inline query result +inputStoryAreaTypeFoundVenue query_id:int64 result_id:string = InputStoryAreaType; + +//@description An area pointing to a venue already added to the story +//@venue_provider Provider of the venue +//@venue_id Identifier of the venue in the provider database +inputStoryAreaTypePreviousVenue venue_provider:string venue_id:string = 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; + + //@description Describes a video file sent in a story //@duration Duration of the video, in seconds //@width Video width @@ -6537,7 +6557,7 @@ sendBotStartMessage bot_user_id:int53 chat_id:int53 parameter:string = Message; //@reply_to Identifier of the replied message or story; pass null if none //@options Options to be used to send the message; pass null to use default options //@query_id Identifier of the inline query -//@result_id Identifier of the inline result +//@result_id Identifier of the inline query result //@hide_via_bot Pass true to hide the bot, via which the message is sent. Can be used only for bots getOption("animation_search_bot_username"), getOption("photo_search_bot_username"), and getOption("venue_search_bot_username") sendInlineQueryResultMessage chat_id:int53 message_thread_id:int53 reply_to:MessageReplyTo options:messageSendOptions query_id:int64 result_id:string hide_via_bot:Bool = Message; diff --git a/td/telegram/Location.cpp b/td/telegram/Location.cpp index a892d23b3..c342002d6 100644 --- a/td/telegram/Location.cpp +++ b/td/telegram/Location.cpp @@ -100,6 +100,19 @@ tl_object_ptr Location::get_input_geo_point() const static_cast(std::ceil(horizontal_accuracy_))); } +telegram_api::object_ptr Location::get_fake_geo_point() const { + if (empty()) { + return make_tl_object(); + } + + int32 flags = 0; + if (horizontal_accuracy_ > 0) { + flags |= telegram_api::geoPoint::ACCURACY_RADIUS_MASK; + } + return telegram_api::make_object(flags, longitude_, latitude_, 0, + static_cast(std::ceil(horizontal_accuracy_))); +} + tl_object_ptr Location::get_input_media_geo_point() const { return make_tl_object(get_input_geo_point()); } diff --git a/td/telegram/Location.h b/td/telegram/Location.h index 9f52fa074..2a3702cb6 100644 --- a/td/telegram/Location.h +++ b/td/telegram/Location.h @@ -56,6 +56,8 @@ class Location { tl_object_ptr get_input_geo_point() const; + telegram_api::object_ptr get_fake_geo_point() const; + tl_object_ptr get_input_media_geo_point() const; double get_latitude() const { diff --git a/td/telegram/MediaArea.cpp b/td/telegram/MediaArea.cpp index dcbbbb1bc..771e9bf89 100644 --- a/td/telegram/MediaArea.cpp +++ b/td/telegram/MediaArea.cpp @@ -6,6 +6,9 @@ // #include "td/telegram/MediaArea.h" +#include "td/telegram/InlineQueriesManager.h" +#include "td/telegram/Td.h" + namespace td { MediaArea::MediaArea(Td *td, telegram_api::object_ptr &&media_area_ptr) { @@ -42,6 +45,58 @@ MediaArea::MediaArea(Td *td, telegram_api::object_ptr & } } +MediaArea::MediaArea(Td *td, td_api::object_ptr &&input_story_area, + const vector &old_media_areas) { + if (input_story_area == nullptr || input_story_area->position_ == nullptr || input_story_area->type_ == nullptr) { + return; + } + coordinates_ = MediaAreaCoordinates(input_story_area->position_); + if (!coordinates_.is_valid()) { + return; + } + switch (input_story_area->type_->get_id()) { + case td_api::inputStoryAreaTypeLocation::ID: { + auto type = td_api::move_object_as(input_story_area->type_); + location_ = Location(type->location_); + if (!location_.empty()) { + type_ = Type::Location; + } + break; + } + case td_api::inputStoryAreaTypeFoundVenue::ID: { + auto type = td_api::move_object_as(input_story_area->type_); + const InlineMessageContent *inline_message_content = + td->inline_queries_manager_->get_inline_message_content(type->query_id_, type->result_id_); + if (inline_message_content == nullptr || inline_message_content->message_content == nullptr) { + break; + } + auto venue_ptr = get_message_content_venue(inline_message_content->message_content.get()); + if (venue_ptr == nullptr || venue_ptr->empty()) { + break; + } + venue_ = *venue_ptr; + input_query_id_ = type->query_id_; + input_result_id_ = std::move(type->result_id_); + type_ = Type::Venue; + break; + } + case td_api::inputStoryAreaTypePreviousVenue::ID: { + auto type = td_api::move_object_as(input_story_area->type_); + for (auto &old_media_area : old_media_areas) { + if (old_media_area.type_ == Type::Venue && !old_media_area.venue_.empty() && + old_media_area.venue_.is_same(type->venue_provider_, type->venue_id_)) { + venue_ = old_media_area.venue_; + type_ = Type::Venue; + break; + } + } + break; + } + default: + UNREACHABLE(); + } +} + td_api::object_ptr MediaArea::get_story_area_object() const { CHECK(is_valid()); td_api::object_ptr type; @@ -58,9 +113,27 @@ td_api::object_ptr MediaArea::get_story_area_object() const { return td_api::make_object(coordinates_.get_story_area_position_object(), std::move(type)); } +telegram_api::object_ptr MediaArea::get_input_media_area() const { + CHECK(is_valid()); + switch (type_) { + case Type::Location: + return telegram_api::make_object(coordinates_.get_input_media_area_coordinates(), + location_.get_fake_geo_point()); + case Type::Venue: + if (input_query_id_ != 0) { + return telegram_api::make_object( + coordinates_.get_input_media_area_coordinates(), input_query_id_, input_result_id_); + } + return venue_.get_input_media_area_venue(coordinates_.get_input_media_area_coordinates()); + default: + UNREACHABLE(); + } +} + 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.venue_ == rhs.venue_ && lhs.input_query_id_ == rhs.input_query_id_ && + lhs.input_result_id_ == rhs.input_result_id_; } bool operator!=(const MediaArea &lhs, const MediaArea &rhs) { diff --git a/td/telegram/MediaArea.h b/td/telegram/MediaArea.h index 8e10f6e69..6e8212343 100644 --- a/td/telegram/MediaArea.h +++ b/td/telegram/MediaArea.h @@ -25,6 +25,8 @@ class MediaArea { MediaAreaCoordinates coordinates_; Location location_; Venue venue_; + int64 input_query_id_ = 0; + string input_result_id_; friend bool operator==(const MediaArea &lhs, const MediaArea &rhs); friend bool operator!=(const MediaArea &lhs, const MediaArea &rhs); @@ -36,8 +38,13 @@ class MediaArea { MediaArea(Td *td, telegram_api::object_ptr &&media_area_ptr); + MediaArea(Td *td, td_api::object_ptr &&input_story_area, + const vector &old_media_areas); + td_api::object_ptr get_story_area_object() const; + telegram_api::object_ptr get_input_media_area() const; + bool is_valid() const { return type_ != Type::None; } diff --git a/td/telegram/MediaArea.hpp b/td/telegram/MediaArea.hpp index a086fa207..364136504 100644 --- a/td/telegram/MediaArea.hpp +++ b/td/telegram/MediaArea.hpp @@ -16,7 +16,9 @@ namespace td { template void MediaArea::store(StorerT &storer) const { using td::store; + bool has_input_query_id = input_query_id_ != 0; BEGIN_STORE_FLAGS(); + STORE_FLAG(has_input_query_id); END_STORE_FLAGS(); store(type_, storer); store(coordinates_, storer); @@ -26,6 +28,10 @@ void MediaArea::store(StorerT &storer) const { break; case Type::Venue: store(venue_, storer); + if (has_input_query_id) { + store(input_query_id_, storer); + store(input_result_id_, storer); + } break; default: UNREACHABLE(); @@ -35,7 +41,9 @@ void MediaArea::store(StorerT &storer) const { template void MediaArea::parse(ParserT &parser) { using td::parse; + bool has_input_query_id; BEGIN_PARSE_FLAGS(); + PARSE_FLAG(has_input_query_id); END_PARSE_FLAGS(); parse(type_, parser); parse(coordinates_, parser); @@ -45,6 +53,10 @@ void MediaArea::parse(ParserT &parser) { break; case Type::Venue: parse(venue_, parser); + if (has_input_query_id) { + parse(input_query_id_, parser); + parse(input_result_id_, parser); + } break; default: parser.set_error("Load invalid area type"); diff --git a/td/telegram/MessageContent.cpp b/td/telegram/MessageContent.cpp index c15b8677c..bb8a6c851 100644 --- a/td/telegram/MessageContent.cpp +++ b/td/telegram/MessageContent.cpp @@ -3500,6 +3500,15 @@ bool get_message_content_poll_is_closed(const Td *td, const MessageContent *cont } } +const Venue *get_message_content_venue(const MessageContent *content) { + switch (content->get_type()) { + case MessageContentType::Venue: + return &static_cast(content)->venue; + default: + return nullptr; + } +} + bool has_message_content_web_page(const MessageContent *content) { if (content->get_type() == MessageContentType::Text) { return static_cast(content)->web_page_id.is_valid(); diff --git a/td/telegram/MessageContent.h b/td/telegram/MessageContent.h index ba1603002..40618df15 100644 --- a/td/telegram/MessageContent.h +++ b/td/telegram/MessageContent.h @@ -44,6 +44,7 @@ class Game; class MultiPromiseActor; struct Photo; class Td; +class Venue; // Do not forget to update merge_message_contents when one of the inheritors of this class changes class MessageContent { @@ -157,6 +158,8 @@ bool get_message_content_poll_is_anonymous(const Td *td, const MessageContent *c bool get_message_content_poll_is_closed(const Td *td, const MessageContent *content); +const Venue *get_message_content_venue(const MessageContent *content); + bool has_message_content_web_page(const MessageContent *content); void remove_message_content_web_page(MessageContent *content); diff --git a/td/telegram/Venue.cpp b/td/telegram/Venue.cpp index 6e14957a6..355950146 100644 --- a/td/telegram/Venue.cpp +++ b/td/telegram/Venue.cpp @@ -76,6 +76,12 @@ tl_object_ptr Venue::get_input_bo flags, location_.get_input_geo_point(), title_, address_, provider_, id_, type_, std::move(reply_markup)); } +telegram_api::object_ptr Venue::get_input_media_area_venue( + telegram_api::object_ptr &&coordinates) const { + return telegram_api::make_object(std::move(coordinates), location_.get_fake_geo_point(), + title_, address_, provider_, id_, type_); +} + bool operator==(const Venue &lhs, const Venue &rhs) { return lhs.location_ == rhs.location_ && lhs.title_ == rhs.title_ && lhs.address_ == rhs.address_ && lhs.provider_ == rhs.provider_ && lhs.id_ == rhs.id_ && lhs.type_ == rhs.type_; diff --git a/td/telegram/Venue.h b/td/telegram/Venue.h index c4de894e8..24d358884 100644 --- a/td/telegram/Venue.h +++ b/td/telegram/Venue.h @@ -45,6 +45,10 @@ class Venue { bool empty() const; + bool is_same(const string &provider, const string &id) const { + return provider_ == provider && id_ == id; + } + Location &location(); const Location &location() const; @@ -58,6 +62,9 @@ class Venue { tl_object_ptr get_input_bot_inline_message_media_venue( tl_object_ptr &&reply_markup) const; + telegram_api::object_ptr get_input_media_area_venue( + telegram_api::object_ptr &&coordinates) const; + template void store(StorerT &storer) const { using td::store;