openstreetmap.py 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109
  1. """
  2. OpenStreetMap (Map)
  3. @website https://openstreetmap.org/
  4. @provide-api yes (http://wiki.openstreetmap.org/wiki/Nominatim)
  5. @using-api yes
  6. @results JSON
  7. @stable yes
  8. @parse url, title
  9. """
  10. import re
  11. from json import loads
  12. from flask_babel import gettext
  13. # engine dependent config
  14. categories = ['map']
  15. paging = False
  16. # search-url
  17. base_url = 'https://nominatim.openstreetmap.org/'
  18. search_string = 'search/{query}?format=json&polygon_geojson=1&addressdetails=1'
  19. result_base_url = 'https://openstreetmap.org/{osm_type}/{osm_id}'
  20. route_url = 'https://graphhopper.com/maps/?point={}&point={}&locale=en-US&vehicle=car&weighting=fastest&turn_costs=true&use_miles=false&layer=Omniscale' # noqa
  21. route_re = re.compile('(?:from )?(.+) to (.+)')
  22. # do search-request
  23. def request(query, params):
  24. params['url'] = base_url + search_string.format(query=query.decode('utf-8'))
  25. params['route'] = route_re.match(query.decode('utf-8'))
  26. return params
  27. # get response from search-request
  28. def response(resp):
  29. results = []
  30. json = loads(resp.text)
  31. if resp.search_params['route']:
  32. results.append({
  33. 'answer': gettext('Get directions'),
  34. 'url': route_url.format(*resp.search_params['route'].groups()),
  35. })
  36. # parse results
  37. for r in json:
  38. if 'display_name' not in r:
  39. continue
  40. title = r['display_name'] or u''
  41. osm_type = r.get('osm_type', r.get('type'))
  42. url = result_base_url.format(osm_type=osm_type,
  43. osm_id=r['osm_id'])
  44. osm = {'type': osm_type,
  45. 'id': r['osm_id']}
  46. geojson = r.get('geojson')
  47. # if no geojson is found and osm_type is a node, add geojson Point
  48. if not geojson and osm_type == 'node':
  49. geojson = {u'type': u'Point', u'coordinates': [r['lon'], r['lat']]}
  50. address_raw = r.get('address')
  51. address = {}
  52. # get name
  53. if r['class'] == 'amenity' or\
  54. r['class'] == 'shop' or\
  55. r['class'] == 'tourism' or\
  56. r['class'] == 'leisure':
  57. if address_raw.get('address29'):
  58. address = {'name': address_raw.get('address29')}
  59. else:
  60. address = {'name': address_raw.get(r['type'])}
  61. # add rest of adressdata, if something is already found
  62. if address.get('name'):
  63. address.update({'house_number': address_raw.get('house_number'),
  64. 'road': address_raw.get('road'),
  65. 'locality': address_raw.get('city',
  66. address_raw.get('town', # noqa
  67. address_raw.get('village'))), # noqa
  68. 'postcode': address_raw.get('postcode'),
  69. 'country': address_raw.get('country'),
  70. 'country_code': address_raw.get('country_code')})
  71. else:
  72. address = None
  73. # append result
  74. results.append({'template': 'map.html',
  75. 'title': title,
  76. 'content': '',
  77. 'longitude': r['lon'],
  78. 'latitude': r['lat'],
  79. 'boundingbox': r['boundingbox'],
  80. 'geojson': geojson,
  81. 'address': address,
  82. 'osm': osm,
  83. 'url': url})
  84. # return results
  85. return results