From bb641253914e4f71d70451816075eb7651814b84 Mon Sep 17 00:00:00 2001 From: Bob Mottram Date: Sat, 21 May 2022 12:36:53 +0100 Subject: [PATCH] Convert map links within post location into an embedded OSM map --- maps.py | 235 ++++++++++++++++++++++++++++++++++++++++++ webapp_create_post.py | 3 +- webapp_post.py | 37 ++++++- 3 files changed, 269 insertions(+), 6 deletions(-) create mode 100644 maps.py diff --git a/maps.py b/maps.py new file mode 100644 index 000000000..5eac5207b --- /dev/null +++ b/maps.py @@ -0,0 +1,235 @@ +__filename__ = "maps.py" +__author__ = "Bob Mottram" +__license__ = "AGPL3+" +__version__ = "1.3.0" +__maintainer__ = "Bob Mottram" +__email__ = "bob@libreserver.org" +__status__ = "Production" +__module_group__ = "Core" + + +def _geocoords_from_osm_link(url: str, osm_domain: str) -> (int, float, float): + """Returns geocoordinates from an OSM map link + """ + if osm_domain + '/#map=' not in url: + return None, None, None + + coords_str = url.split('openstreetmap.org/#map=')[1] + if '/' not in coords_str: + return None, None, None + + coords = coords_str.split('/') + if len(coords) != 3: + return None, None, None + zoom = coords[0] + if not zoom.isdigit(): + return None, None, None + latitude = coords[1] + if not latitude.isdigit(): + return None, None, None + longitude = coords[2] + if not longitude.isdigit(): + return None, None, None + zoom = int(zoom) + latitude = float(latitude) + longitude = float(longitude) + return zoom, latitude, longitude + + +def _geocoords_from_gmaps_link(url: str) -> (int, float, float): + """Returns geocoordinates from a Gmaps link + """ + if '/maps/@' not in url: + return None, None, None + + coords_str = url.split('/maps/@')[1] + if ',' not in coords_str: + return None, None, None + + coords = coords_str.split(',') + if len(coords) != 3: + return None, None, None + zoom = coords[2].replace('z', '') + if not zoom.isdigit(): + return None, None, None + latitude = coords[0] + if not latitude.isdigit(): + return None, None, None + longitude = coords[1] + if not longitude.isdigit(): + return None, None, None + zoom = int(zoom) + latitude = float(latitude) + longitude = float(longitude) + return zoom, latitude, longitude + + +def _geocoords_from_bmaps_link(url: str) -> (int, float, float): + """Returns geocoordinates from a bing map link + """ + prefixes = ('/maps?cp=', '/maps/directions?cp=') + map_prefix = None + for prefix in prefixes: + if prefix in url: + map_prefix = prefix + break + if not map_prefix: + return None, None, None + + coords_str = url.split(map_prefix)[1] + if '~' not in coords_str: + return None, None, None + orig_coords_str = coords_str + if '&' in coords_str: + coords_str = coords_str.split('&')[0] + if ';' in coords_str: + coords_str = coords_str.split(';')[0] + + coords = coords_str.split('~') + if len(coords) != 2: + return None, None, None + latitude = coords[0] + if not latitude.isdigit(): + return None, None, None + longitude = coords[1] + if not longitude.isdigit(): + return None, None, None + zoom = 17 + if 'lvl=' in orig_coords_str: + zoom = orig_coords_str.split('lvl=')[1] + if '&' in zoom: + zoom = zoom.split('&')[0] + if ';' in zoom: + zoom = zoom.split(';')[0] + if not zoom.isdigit(): + return None, None, None + zoom = int(zoom) + latitude = float(latitude) + longitude = float(longitude) + return zoom, latitude, longitude + + +def _geocoords_from_waze_link(url: str) -> (int, float, float): + """Returns geocoordinates from a waze map link + """ + prefixes = ['/ul?ll='] + map_prefix = None + for prefix in prefixes: + if prefix in url: + map_prefix = prefix + break + if not map_prefix: + return None, None, None + + coords_str = url.split(map_prefix)[1] + orig_coords_str = coords_str + if '&' in coords_str: + coords_str = coords_str.split('&')[0] + if '%2C' not in coords_str and ',' not in coords_str: + return None, None, None + + if '%2C' in coords_str: + coords = coords_str.split('%2C') + else: + coords = coords_str.split(',') + if len(coords) != 2: + return None, None, None + latitude = coords[0] + if not latitude.isdigit(): + return None, None, None + longitude = coords[1] + if not longitude.isdigit(): + return None, None, None + zoom = 17 + if 'zoom=' in orig_coords_str: + zoom = orig_coords_str.split('zoom=')[1] + if '&' in zoom: + zoom = zoom.split('&')[0] + if not zoom.isdigit(): + return None, None, None + zoom = int(zoom) + latitude = float(latitude) + longitude = float(longitude) + return zoom, latitude, longitude + + +def _geocoords_from_wego_link(url: str) -> (int, float, float): + """Returns geocoordinates from a wego map link + """ + prefixes = ['/?map='] + map_prefix = None + for prefix in prefixes: + if prefix in url: + map_prefix = prefix + break + if not map_prefix: + return None, None, None + + coords_str = url.split(map_prefix)[1] + if ',' not in coords_str: + return None, None, None + + coords = coords_str.split(',') + if len(coords) < 3: + return None, None, None + latitude = coords[0] + if not latitude.isdigit(): + return None, None, None + longitude = coords[1] + if not longitude.isdigit(): + return None, None, None + zoom = coords[2] + if not zoom.isdigit(): + return None, None, None + zoom = int(zoom) + latitude = float(latitude) + longitude = float(longitude) + return zoom, latitude, longitude + + +def _geocoords_from_map_link(url: str, osm_domain: str) -> (int, float, float): + """Returns geocoordinates from a map link url + """ + if osm_domain in url: + return _geocoords_from_osm_link(url, osm_domain) + elif '.google.co' in url: + return _geocoords_from_gmaps_link(url) + elif '.bing.co' in url: + return _geocoords_from_bmaps_link(url) + elif '.waze.co' in url: + return _geocoords_from_waze_link(url) + elif 'wego.here.co' in url: + return _geocoords_from_wego_link(url) + return None, None, None + + +def html_open_street_map(url: str, + bounding_box_degrees: float, + translate: {}) -> str: + """Returns embed html for an OSM link + """ + osm_domain = 'openstreetmap.org' + zoom, latitude, longitude = _geocoords_from_map_link(url, osm_domain) + if not latitude: + return '' + if not longitude: + return '' + if not zoom: + return '' + + html_str = \ + '' + \ + '
' + translate['View Larger Map'] + '\n' + return html_str diff --git a/webapp_create_post.py b/webapp_create_post.py index 888b9e1c4..651c9d22b 100644 --- a/webapp_create_post.py +++ b/webapp_create_post.py @@ -682,7 +682,8 @@ def html_new_post(css_cache: {}, media_instance: bool, translate: {}, date_and_location += date_and_time_str date_and_location += \ - edit_text_field(translate['Location'], 'location', '') + edit_text_field(translate['Location'], 'location', + 'https://www.openstreetmap.org/#map=') date_and_location += end_edit_section() instance_title = get_config_param(base_dir, 'instanceTitle') diff --git a/webapp_post.py b/webapp_post.py index e7b95c5b9..0ea90e8d0 100644 --- a/webapp_post.py +++ b/webapp_post.py @@ -93,6 +93,21 @@ from languages import auto_translate_post from blocking import is_blocked from blocking import add_cw_from_lists from reaction import html_emoji_reactions +from maps import html_open_street_map + + +def _get_location_from_tags(tags: []) -> str: + """Returns the location from the tags list + """ + for tag_item in tags: + if not tag_item.get('type'): + continue + if tag_item['type'] != 'Place': + continue + if not tag_item.get('name'): + continue + return tag_item['name'].replace('\n', ' ') + return None def _html_post_metadata_open_graph(domain: str, post_json_object: {}, @@ -2128,11 +2143,23 @@ def individual_post_as_html(signing_priv_key_pem: str, _log_post_timing(enable_timing_log, post_start_time, '17') - if post_json_object['object'].get('tag') and not is_patch: - content_str = \ - replace_emoji_from_tags(session, base_dir, content_str, - post_json_object['object']['tag'], - 'content', False, True) + if post_json_object['object'].get('tag'): + if not is_patch: + content_str = \ + replace_emoji_from_tags(session, base_dir, content_str, + post_json_object['object']['tag'], + 'content', False, True) + + # show embedded map if the location contains a map url + location_str = \ + _get_location_from_tags(post_json_object['object']['tag']) + if location_str: + if '://' in location_str and '.' in location_str: + bounding_box_degrees = 0.01 + content_str += \ + html_open_street_map(location_str, + bounding_box_degrees, + translate) if is_muted: content_str = ''