diff --git a/td/generate/scheme/td_api.tl b/td/generate/scheme/td_api.tl index d915dc9b1..a9c96463e 100644 --- a/td/generate/scheme/td_api.tl +++ b/td/generate/scheme/td_api.tl @@ -293,7 +293,8 @@ voiceNote duration:int32 waveform:bytes mime_type:string voice:file = VoiceNote; contact phone_number:string first_name:string last_name:string vcard:string user_id:int32 = Contact; //@description Describes a location on planet Earth @latitude Latitude of the location in degrees; as defined by the sender @longitude Longitude of the location, in degrees; as defined by the sender -location latitude:double longitude:double = Location; +//@horizontal_accuracy The estimated horizontal accuracy of the location, in meters; as defined by the sender. 0 if unknown +location latitude:double longitude:double horizontal_accuracy:double = Location; //@description Describes a venue @location Venue location; as defined by the sender @title Venue name; as defined by the sender @address Venue address; as defined by the sender @provider Provider of the venue database; as defined by the sender. Currently only "foursquare" and "gplaces" (Google Places) need to be supported //@id Identifier of the venue in the provider database; as defined by the sender @type Type of the venue in the provider database; as defined by the sender diff --git a/td/generate/scheme/td_api.tlo b/td/generate/scheme/td_api.tlo index f347a5fde..f7384d4fe 100644 Binary files a/td/generate/scheme/td_api.tlo and b/td/generate/scheme/td_api.tlo differ diff --git a/td/generate/scheme/telegram_api.tl b/td/generate/scheme/telegram_api.tl index d41cda21b..067f911a3 100644 --- a/td/generate/scheme/telegram_api.tl +++ b/td/generate/scheme/telegram_api.tl @@ -65,7 +65,7 @@ inputChatUploadedPhoto#c642724e flags:# file:flags.0?InputFile video:flags.1?Inp inputChatPhoto#8953ad37 id:InputPhoto = InputChatPhoto; inputGeoPointEmpty#e4c123d6 = InputGeoPoint; -inputGeoPoint#f3b7acc9 lat:double long:double = InputGeoPoint; +inputGeoPoint#48222faf flags:# lat:double long:double accuracy_radius:flags.0?int = InputGeoPoint; inputPhotoEmpty#1cd7bf0d = InputPhoto; inputPhoto#3bb3b94a id:long access_hash:long file_reference:bytes = InputPhoto; @@ -182,7 +182,7 @@ photoStrippedSize#e0b0bc2e type:string bytes:bytes = PhotoSize; photoSizeProgressive#5aa86a51 type:string location:FileLocation w:int h:int sizes:Vector = PhotoSize; geoPointEmpty#1117dd5f = GeoPoint; -geoPoint#296f104 long:double lat:double access_hash:long = GeoPoint; +geoPoint#b2a2f663 flags:# long:double lat:double access_hash:long accuracy_radius:flags.0?int = GeoPoint; auth.sentCode#5e002502 flags:# type:auth.SentCodeType phone_code_hash:string next_type:flags.1?auth.CodeType timeout:flags.2?int = auth.SentCode; diff --git a/td/generate/scheme/telegram_api.tlo b/td/generate/scheme/telegram_api.tlo index e98cc1f34..ea5182bbb 100644 Binary files a/td/generate/scheme/telegram_api.tlo and b/td/generate/scheme/telegram_api.tlo differ diff --git a/td/telegram/InlineQueriesManager.cpp b/td/telegram/InlineQueriesManager.cpp index 97aee407d..ea2745537 100644 --- a/td/telegram/InlineQueriesManager.cpp +++ b/td/telegram/InlineQueriesManager.cpp @@ -505,7 +505,8 @@ void InlineQueriesManager::answer_inline_query(int64 inline_query_id, bool is_pe type = "geo"; id = std::move(location->id_); title = std::move(location->title_); - description = PSTRING() << location->location_->latitude_ << ' ' << location->location_->longitude_; + description = PSTRING() << location->location_->latitude_ << ' ' << location->location_->longitude_ << ' ' + << location->location_->horizontal_accuracy_; thumbnail_url = std::move(location->thumbnail_url_); // duration = location->live_period_; if (!thumbnail_url.empty()) { @@ -972,7 +973,7 @@ tl_object_ptr copy(const td_api::contact &obj) { template <> tl_object_ptr copy(const td_api::location &obj) { - return make_tl_object(obj.latitude_, obj.longitude_); + return make_tl_object(obj.latitude_, obj.longitude_, obj.horizontal_accuracy_); } template <> @@ -1381,8 +1382,12 @@ void InlineQueriesManager::on_get_inline_query_results(UserId bot_user_id, uint6 Location l(inline_message_geo->geo_); location->location_ = l.get_location_object(); } else { - auto coordinates = split(Slice(result->description_)); - Location l(to_double(coordinates.first), to_double(coordinates.second), 0); + Slice latitude; + Slice longitude; + Slice horizontal_accuracy; + std::tie(latitude, longitude) = split(Slice(result->description_)); + std::tie(longitude, horizontal_accuracy) = split(longitude); + Location l(to_double(latitude), to_double(longitude), to_double(horizontal_accuracy), 0); location->location_ = l.get_location_object(); } location->thumbnail_ = register_thumbnail(std::move(result->thumb_)); diff --git a/td/telegram/Location.cpp b/td/telegram/Location.cpp index 8cb599be1..08a2a43ad 100644 --- a/td/telegram/Location.cpp +++ b/td/telegram/Location.cpp @@ -10,22 +10,33 @@ namespace td { -void Location::init(double latitude, double longitude, int64 access_hash) { +double Location::fix_accuracy(double accuracy) { + if (!std::isfinite(accuracy) || accuracy <= 0.0) { + return 0.0; + } + if (accuracy >= 1000.0) { + return 1000.0; + } + return accuracy; +} + +void Location::init(double latitude, double longitude, double horizontal_accuracy, int64 access_hash) { if (std::isfinite(latitude) && std::isfinite(longitude) && std::abs(latitude) <= 90 && std::abs(longitude) <= 180) { is_empty_ = false; latitude_ = latitude; longitude_ = longitude; + horizontal_accuracy_ = fix_accuracy(horizontal_accuracy); access_hash_ = access_hash; G()->add_location_access_hash(latitude_, longitude_, access_hash_); } } -Location::Location(double latitude, double longitude, int64 access_hash) { - init(latitude, longitude, access_hash); +Location::Location(double latitude, double longitude, double horizontal_accuracy, int64 access_hash) { + init(latitude, longitude, horizontal_accuracy, access_hash); } Location::Location(const tl_object_ptr &geo_point) - : Location(geo_point->lat_, geo_point->long_, 0) { + : Location(geo_point->lat_, geo_point->long_, 0.0, 0) { } Location::Location(const tl_object_ptr &geo_point_ptr) { @@ -37,7 +48,7 @@ Location::Location(const tl_object_ptr &geo_point_ptr) { break; case telegram_api::geoPoint::ID: { auto geo_point = static_cast(geo_point_ptr.get()); - init(geo_point->lat_, geo_point->long_, geo_point->access_hash_); + init(geo_point->lat_, geo_point->long_, geo_point->accuracy_radius_, geo_point->access_hash_); break; } default: @@ -51,7 +62,7 @@ Location::Location(const tl_object_ptr &location) { return; } - init(location->latitude_, location->longitude_, 0); + init(location->latitude_, location->longitude_, location->horizontal_accuracy_, 0); } bool Location::empty() const { @@ -67,7 +78,7 @@ tl_object_ptr Location::get_location_object() const { if (empty()) { return nullptr; } - return make_tl_object(latitude_, longitude_); + return make_tl_object(latitude_, longitude_, horizontal_accuracy_); } tl_object_ptr Location::get_input_geo_point() const { @@ -75,7 +86,13 @@ tl_object_ptr Location::get_input_geo_point() const return make_tl_object(); } - return make_tl_object(latitude_, longitude_); + int32 flags = 0; + if (horizontal_accuracy_ > 0) { + flags |= telegram_api::inputGeoPoint::ACCURACY_RADIUS_MASK; + } + + return make_tl_object(flags, latitude_, longitude_, + static_cast(std::ceil(horizontal_accuracy_))); } tl_object_ptr Location::get_input_media_geo_point() const { @@ -91,7 +108,8 @@ bool operator==(const Location &lhs, const Location &rhs) { return rhs.is_empty_; } return !rhs.is_empty_ && std::abs(lhs.latitude_ - rhs.latitude_) < 1e-6 && - std::abs(lhs.longitude_ - rhs.longitude_) < 1e-6; + std::abs(lhs.longitude_ - rhs.longitude_) < 1e-6 && + std::abs(lhs.horizontal_accuracy_ - rhs.horizontal_accuracy_) < 1e-6; } bool operator!=(const Location &lhs, const Location &rhs) { @@ -103,7 +121,7 @@ StringBuilder &operator<<(StringBuilder &string_builder, const Location &locatio return string_builder << "Location[empty]"; } return string_builder << "Location[latitude = " << location.latitude_ << ", longitude = " << location.longitude_ - << "]"; + << ", accuracy = " << location.horizontal_accuracy_ << "]"; } Result process_input_message_location( diff --git a/td/telegram/Location.h b/td/telegram/Location.h index 17a21f198..0cdcf064c 100644 --- a/td/telegram/Location.h +++ b/td/telegram/Location.h @@ -24,6 +24,7 @@ class Location { bool is_empty_ = true; double latitude_ = 0.0; double longitude_ = 0.0; + double horizontal_accuracy_ = 0.0; mutable int64 access_hash_ = 0; friend bool operator==(const Location &lhs, const Location &rhs); @@ -31,12 +32,14 @@ class Location { friend StringBuilder &operator<<(StringBuilder &string_builder, const Location &location); - void init(double latitude, double longitude, int64 access_hash); + void init(double latitude, double longitude, double horizontal_accuracy, int64 access_hash); + + double fix_accuracy(double accuracy); public: Location() = default; - Location(double latitude, double longitude, int64 access_hash); + Location(double latitude, double longitude, double horizontal_accuracy, int64 access_hash); explicit Location(const tl_object_ptr &geo_point); @@ -76,24 +79,31 @@ class Location { void store(StorerT &storer) const { using td::store; bool has_access_hash = access_hash_ != 0; + bool has_horizontal_accuracy = horizontal_accuracy_ > 0.0; BEGIN_STORE_FLAGS(); STORE_FLAG(is_empty_); STORE_FLAG(has_access_hash); + STORE_FLAG(has_horizontal_accuracy); END_STORE_FLAGS(); store(latitude_, storer); store(longitude_, storer); if (has_access_hash) { store(access_hash_, storer); } + if (has_horizontal_accuracy) { + store(horizontal_accuracy_, storer); + } } template void parse(ParserT &parser) { using td::parse; bool has_access_hash; + bool has_horizontal_accuracy; BEGIN_PARSE_FLAGS(); PARSE_FLAG(is_empty_); PARSE_FLAG(has_access_hash); + PARSE_FLAG(has_horizontal_accuracy); END_PARSE_FLAGS(); parse(latitude_, parser); parse(longitude_, parser); @@ -101,6 +111,9 @@ class Location { parse(access_hash_, parser); G()->add_location_access_hash(latitude_, longitude_, access_hash_); } + if (has_horizontal_accuracy) { + parse(horizontal_accuracy_, parser); + } } }; diff --git a/td/telegram/MessageContent.cpp b/td/telegram/MessageContent.cpp index bfdd40189..ae7dbb02e 100644 --- a/td/telegram/MessageContent.cpp +++ b/td/telegram/MessageContent.cpp @@ -3674,7 +3674,7 @@ unique_ptr get_secret_message_content( message_venue->venue_id_.clear(); } - auto m = make_unique(Venue(Location(message_venue->lat_, message_venue->long_, 0), + auto m = make_unique(Venue(Location(message_venue->lat_, message_venue->long_, 0.0, 0), std::move(message_venue->title_), std::move(message_venue->address_), std::move(message_venue->provider_), std::move(message_venue->venue_id_), string())); diff --git a/td/telegram/cli.cpp b/td/telegram/cli.cpp index 53c1f9a4d..dd77bf381 100644 --- a/td/telegram/cli.cpp +++ b/td/telegram/cli.cpp @@ -635,11 +635,11 @@ class CliClient final : public Actor { return to_integer(trim(std::move(str))); } - static td_api::object_ptr as_location(string latitude, string longitude) { + static td_api::object_ptr as_location(string latitude, string longitude, string accuracy = "") { if (trim(latitude).empty() && trim(longitude).empty()) { return nullptr; } - return td_api::make_object(to_double(latitude), to_double(longitude)); + return td_api::make_object(to_double(latitude), to_double(longitude), to_double(accuracy)); } static bool as_bool(string str) { @@ -3128,14 +3128,16 @@ class CliClient final : public Actor { string message_id; string latitude; string longitude; + string accuracy; string heading; std::tie(chat_id, args) = split(args); std::tie(message_id, args) = split(args); std::tie(latitude, args) = split(args); - std::tie(longitude, heading) = split(args); - send_request(td_api::make_object(as_chat_id(chat_id), as_message_id(message_id), - nullptr, as_location(latitude, longitude), - to_integer(heading))); + std::tie(longitude, args) = split(args); + std::tie(accuracy, heading) = split(args); + send_request(td_api::make_object( + as_chat_id(chat_id), as_message_id(message_id), nullptr, as_location(latitude, longitude, accuracy), + to_integer(heading))); } else if (op == "emss") { string chat_id; string message_id; @@ -3383,27 +3385,31 @@ class CliClient final : public Actor { send_message(chat_id, td_api::make_object(as_user_id(bot_user_id), game_short_name)); } else if (op == "sl") { string chat_id; - std::tie(chat_id, args) = split(args); - string latitude; string longitude; - std::tie(latitude, longitude) = split(args); + string accuracy; + std::tie(chat_id, args) = split(args); + std::tie(latitude, args) = split(args); + std::tie(longitude, accuracy) = split(args); - send_message(chat_id, td_api::make_object(as_location(latitude, longitude), 0, 0)); + send_message(chat_id, + td_api::make_object(as_location(latitude, longitude, accuracy), 0, 0)); } else if (op == "sll") { string chat_id; string period; - string heading; string latitude; string longitude; + string accuracy; + string heading; std::tie(chat_id, args) = split(args); std::tie(period, args) = split(args); - std::tie(heading, args) = split(args); - std::tie(latitude, longitude) = split(args); + std::tie(latitude, args) = split(args); + std::tie(longitude, args) = split(args); + std::tie(accuracy, heading) = split(args); - send_message(chat_id, - td_api::make_object( - as_location(latitude, longitude), to_integer(period), to_integer(heading))); + send_message(chat_id, td_api::make_object( + as_location(latitude, longitude, accuracy), to_integer(period), + to_integer(heading))); } else if (op == "spoll" || op == "spollm" || op == "spollp" || op == "squiz") { string chat_id; string question; @@ -3552,6 +3558,7 @@ class CliClient final : public Actor { string latitude; string longitude; + string accuracy; string title; string address; string provider; @@ -3560,13 +3567,15 @@ class CliClient final : public Actor { std::tie(chat_id, args) = split(args); std::tie(latitude, args) = split(args); std::tie(longitude, args) = split(args); + std::tie(accuracy, args) = split(args); std::tie(title, args) = split(args); std::tie(address, args) = split(args); std::tie(provider, args) = split(args); std::tie(venue_id, venue_type) = split(args); - send_message(chat_id, td_api::make_object(td_api::make_object( - as_location(latitude, longitude), title, address, provider, venue_id, venue_type))); + send_message(chat_id, + td_api::make_object(td_api::make_object( + as_location(latitude, longitude, accuracy), title, address, provider, venue_id, venue_type))); } else if (op == "test") { send_request(td_api::make_object()); } else if (op == "alarm") { @@ -3597,7 +3606,7 @@ class CliClient final : public Actor { } else if (op == "cngc") { send_request(td_api::make_object( args, false, "Description", - td_api::make_object(td_api::make_object(40.0, 60.0), "address"))); + td_api::make_object(as_location("40.0", "60.0"), "address"))); } else if (op == "UpgradeBasicGroupChatToSupergroupChat") { send_request(td_api::make_object(as_chat_id(args))); } else if (op == "DeleteSupergroup") { diff --git a/td/telegram/files/FileGenerateManager.cpp b/td/telegram/files/FileGenerateManager.cpp index 27f14be1f..47671dbac 100644 --- a/td/telegram/files/FileGenerateManager.cpp +++ b/td/telegram/files/FileGenerateManager.cpp @@ -190,7 +190,8 @@ class MapDownloadGenerateActor : public FileGenerateActor { int64 access_hash = G()->get_location_access_hash(latitude, longitude); return make_tl_object( - make_tl_object(latitude, longitude), access_hash, width, height, zoom, scale); + make_tl_object(0, latitude, longitude, 0), access_hash, width, height, zoom, + scale); } void start_up() override {