diff --git a/README.md b/README.md index 44290f5b..3647cdd4 100644 --- a/README.md +++ b/README.md @@ -503,9 +503,11 @@ Get statistics by medias. Common arguments: | Method | Return | Description | | ---------------------------------------------------------- | -------------- | ----------------------------------------------------------------------- | | location_search(lat: float, lng: float) | List[Location] | Search Location by GEO coordinates +| location_search_name(LocationName: String) | List[Location] | Search Location by Name +| location_search_pk(location: Location) | Location | Return Location info (pk, name, address, lng, lat, external_id, external_id_source,precision) | location_complete(location: Location) | Location | Complete blank fields | location_build(location: Location) | String | Serialized JSON -| location_info(location_pk: int) | Location | Return Location info (pk, name, address, lng, lat, external_id, external_id_source) +| location_info(location_pk: int) | Location | Return Location info (pk, name, address, lng, lat) | location_medias_top(location_pk: int, amount: int = 9) | List[Media] | Return Top posts by Location | location_medias_recent(location_pk: int, amount: int = 24) | List[Media] | Return Most recent posts by Location diff --git a/examples/location_search.py b/examples/location_search.py new file mode 100644 index 00000000..4299f808 --- /dev/null +++ b/examples/location_search.py @@ -0,0 +1,18 @@ +from instagrapi import Client + +cl = Client() +cl.login("YOUR_LOGIN", "YOUR_PASSWORD") + +loc=cl.location_search(59.93318, 30.30605) +print(loc) +print("-") +print("-") + +loc1=cl.location_search_pk(107617247320879) +print(loc1) +print("-") +print("-") + + +loc2=cl.location_search_name("Choroni") +print(loc2) \ No newline at end of file diff --git a/instagrapi/extractors.py b/instagrapi/extractors.py index 181af70c..d2ba6465 100644 --- a/instagrapi/extractors.py +++ b/instagrapi/extractors.py @@ -157,6 +157,11 @@ def extract_location(data): """Extract location info""" if not data: return None + + if "place" in data: + if "location" in data["place"]: + data=data["place"]["location"] + data["pk"] = data.get("id", data.get("pk", None)) data["external_id"] = data.get("external_id", data.get("facebook_places_id")) data["external_id_source"] = data.get( diff --git a/instagrapi/mixins/location.py b/instagrapi/mixins/location.py index 4de8f692..c9d8ad76 100644 --- a/instagrapi/mixins/location.py +++ b/instagrapi/mixins/location.py @@ -1,5 +1,6 @@ import json import time +from math import atan2, cos, radians, sin, sqrt from typing import List from instagrapi.exceptions import (ClientLoginRequired, ClientNotFoundError, @@ -35,13 +36,69 @@ def location_search(self, lat: float, lng: float) -> List[Location]: # rankToken=c544eea5-726b-4091-a916-a71a35a76474 - self.uuid? # fb_access_token=EAABwzLixnjYBABK2YBFkT...pKrjju4cijEGYtcbIyCSJ0j4ZD } + #Calculate approximate radius of earth in km + R = 6373.0 + lat1 = radians(lat) + lon1 = radians(lng) result = self.private_request("location_search/", params=params) locations = [] for venue in result["venues"]: - if "lat" not in venue: - venue["lat"] = lat - venue["lng"] = lng - locations.append(extract_location(venue)) + if "lat" in venue: + lat2 = radians(venue["lat"]) + lon2 = radians(venue["lng"]) + dlon = lon2 - lon1 + dlat = lat2 - lat1 + a = sin(dlat / 2)**2 + cos(lat1) * cos(lat2) * sin(dlon / 2)**2 + c = 2 * atan2(sqrt(a), sqrt(1 - a)) + precision = R * c + #return approximate of two coordinates in km + if precision < 1: + loc=extract_location(venue) + loc.precision=precision + locations.append(loc) + return sorted(locations, key=lambda k: k.precision) + + def location_search_pk(self, pk: int) -> Location: + """ + Get locations using pk + + Parameters + ---------- + pk: int + id + Returns + ------- + Location + An object of Location + """ + result = self.top_search(self.location_info(pk).name) + + location = "{}" + for places in result["places"]: + single_location=extract_location(places) + if single_location.pk==pk: + location=single_location + + return location + + def location_search_name(self, LocationName: str) -> List[Location]: + """ + Get locations using name + + Parameters + ---------- + LocationName: string + LocationName + Returns + ------- + List[Location] + List of objects of Location + """ + result = self.top_search(LocationName) + locations = [] + for places in result["places"]: + locations.append(extract_location(places)) + return locations def location_complete(self, location: Location) -> Location: diff --git a/instagrapi/types.py b/instagrapi/types.py index 6bec43f0..866a91a2 100644 --- a/instagrapi/types.py +++ b/instagrapi/types.py @@ -66,6 +66,7 @@ class Location(BaseModel): lat: Optional[float] external_id: Optional[int] external_id_source: Optional[str] + precision: Optional[int] # address_json: Optional[dict] = {} # profile_pic_url: Optional[HttpUrl] # directory: Optional[dict] = {} diff --git a/tests.py b/tests.py index 8a20edae..88d51d64 100644 --- a/tests.py +++ b/tests.py @@ -77,7 +77,7 @@ class FakeClientTestCase(BaseClientMixin, unittest.TestCase): def test_login(self): try: - self.api.login(ACCOUNT_USERNAME, "fakepassword") + self.api.login(ACCOUNT_USERNAME, "yoa5af6deeRujeec") except Exception as e: self.assertEqual( str(e), "The password you entered is incorrect. Please try again." @@ -719,7 +719,7 @@ def test_extract_media_igtv(self): class ClienUploadTestCase(ClientPrivateTestCase): def get_location(self): - location = self.api.location_search(lat=59.939095, lng=30.315868)[0] + location = self.api.location_search(lat=59.93318, lng=30.30605)[0] self.assertIsInstance(location, Location) return location @@ -729,8 +729,8 @@ def assertLocation(self, location): dict( pk=213597007, name='Palace Square', - lat=59.939166666667, - lng=30.315833333333 + lat=59.938961072984, + lng=30.316096544266 ), dict( pk=107617247320879, @@ -973,13 +973,27 @@ def test_account_change_picture(self): class ClientLocationTestCase(ClientPrivateTestCase): def test_location_search(self): - loc = self.api.location_search(51.0536111111, 13.8108333333)[0] + loc = self.api.location_search(51.053157024486, 13.812078650852)[0] self.assertIsInstance(loc, Location) self.assertIn('Dresden', loc.name) self.assertIn('Dresden', loc.address) self.assertEqual(150300262230285, loc.external_id) self.assertEqual('facebook_places', loc.external_id_source) + def test_location_search_pk(self): + loc = self.api.location_search_pk(239130043) + self.assertIsInstance(loc, Location) + self.assertIn('ChoronĂ­', loc.name) + self.assertEqual(108835465815492, loc.external_id) + self.assertEqual('facebook_places', loc.external_id_source) + + def test_location_search_name(self): + loc = self.api.location_search("ChoronĂ­")[0] + self.assertIsInstance(loc, Location) + self.assertIn('ChoronĂ­', loc.name) + self.assertEqual(108835465815492, loc.external_id) + self.assertEqual('facebook_places', loc.external_id_source) + def test_location_complete_pk(self): source = Location( name='Daily Surf Supply', @@ -997,14 +1011,14 @@ def test_location_complete_lat_lng(self): ) result = self.api.location_complete(source) self.assertIsInstance(result, Location) - self.assertEqual(result.lat, 51.0536111111) - self.assertEqual(result.lng, 13.8108333333) + self.assertEqual(result.lat, 51.053157024486) + self.assertEqual(result.lng, 13.812078650852) def test_location_complete_external_id(self): source = Location( name='Blaues Wunder (Dresden)', - lat=51.0536111111, - lng=13.8108333333 + lat=51.053157024486, + lng=13.812078650852 ) result = self.api.location_complete(source) self.assertIsInstance(result, Location) @@ -1022,8 +1036,8 @@ def test_location_build(self): data, { "name": "Blaues Wunder (Dresden)", "address": "Dresden, Germany", - "lat": 51.053611111111, - "lng": 13.810833333333, + "lat": 51.053157024486, + "lng": 13.812078650852, "facebook_places_id": 150300262230285, "external_source": "facebook_places", } @@ -1034,8 +1048,8 @@ def test_location_info(self): self.assertIsInstance(loc, Location) self.assertEqual(loc.pk, 150300262230285) self.assertEqual(loc.name, 'Blaues Wunder (Dresden)') - self.assertEqual(loc.lng, 13.8108333333) - self.assertEqual(loc.lat, 51.0536111111) + self.assertEqual(loc.lng, 13.812078650852) + self.assertEqual(loc.lat, 51.053157024486) def test_location_info_without_lat_lng(self): loc = self.api.location_info(197780767581661)