random_street_view.py 2.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970
  1. import random
  2. import requests
  3. from .shared import point_has_streetview, GeoPointSource, CachedGeoPointSource, ExhaustedSourceError, GeoPointSourceGroup
  4. RSV_URL = "https://randomstreetview.com/data"
  5. VALID_COUNTRIES = ("ad", "au", "ar", "bd", "be", "bt", "bw",
  6. "br", "bg", "kh", "ca", "cl", "hr", "co",
  7. "cz", "dk", "ae", "ee", "fi", "fr", "de",
  8. "gr", "hu", "hk", "is", "id", "ie", "it",
  9. "il", "jp", "lv", "lt", "my", "mx", "nl",
  10. "nz", "no", "pe", "pl", "pt", "ro", "ru",
  11. "sg", "sk", "si", "za", "kr", "es", "sz",
  12. "se", "ch", "tw", "th", "ua", "gb", "us")
  13. def call_random_street_view(country_lock=None):
  14. """
  15. Returns an array of (some number of) tuples, each being (latitude, longitude).
  16. All points will be valid streetview coordinates. There is no guarantee as to the
  17. length of this array (it may be empty), but it will never be None.
  18. This function calls the streetview metadata endpoint - there is no quota consumed.
  19. """
  20. if country_lock is None:
  21. # TODO this is WRONG - this makes them all from one country!
  22. # this whole logic needs to be tweaked - maybe just cache points by country?
  23. # a world game should pick a random country N times
  24. country_lock = random.choice(VALID_COUNTRIES)
  25. try:
  26. rsv_js = requests.post(RSV_URL, data={"country": country_lock.lower()}).json()
  27. except:
  28. return []
  29. if not rsv_js["success"]:
  30. return []
  31. return [
  32. (country_lock, point["lat"], point["lng"])
  33. for point in rsv_js["locations"]
  34. if point_has_streetview(point["lat"], point["lng"])
  35. ]
  36. class RSVPointSource(GeoPointSource):
  37. def __init__(self, country_lock=None, max_attempts=100):
  38. self.country_lock = country_lock
  39. self.max_attempts = max_attempts
  40. def get_name(self):
  41. return f"RSV-{self.country_lock or 'all'}"
  42. def get_points(self, n):
  43. attempts = 0
  44. points = []
  45. while len(points) < n:
  46. if attempts > self.max_attempts:
  47. raise ExhaustedSourceError(points)
  48. points.extend(call_random_street_view(country_lock=self.country_lock))
  49. attempts += 1
  50. return points
  51. WORLD_SOURCE = CachedGeoPointSource(RSVPointSource(), 10)
  52. COUNTRY_SOURCES = {
  53. "us": CachedGeoPointSource(RSVPointSource("us"), 10), # cache US specifically since it is commonly used
  54. **{ k: RSVPointSource(k) for k in VALID_COUNTRIES if k not in ("us",) }
  55. }
  56. SOURCE_GROUP = GeoPointSourceGroup(COUNTRY_SOURCES, WORLD_SOURCE)