2022-05-21 11:36:53 +00:00
|
|
|
__filename__ = "maps.py"
|
|
|
|
__author__ = "Bob Mottram"
|
|
|
|
__license__ = "AGPL3+"
|
|
|
|
__version__ = "1.3.0"
|
|
|
|
__maintainer__ = "Bob Mottram"
|
|
|
|
__email__ = "bob@libreserver.org"
|
|
|
|
__status__ = "Production"
|
|
|
|
__module_group__ = "Core"
|
|
|
|
|
|
|
|
|
2022-05-22 12:37:57 +00:00
|
|
|
import os
|
2022-05-21 12:23:29 +00:00
|
|
|
from utils import is_float
|
2022-05-22 12:37:57 +00:00
|
|
|
from utils import acct_dir
|
|
|
|
from utils import load_json
|
|
|
|
from utils import save_json
|
2022-05-21 12:23:29 +00:00
|
|
|
|
|
|
|
|
2022-05-21 11:36:53 +00:00
|
|
|
def _geocoords_from_osm_link(url: str, osm_domain: str) -> (int, float, float):
|
|
|
|
"""Returns geocoordinates from an OSM map link
|
|
|
|
"""
|
2022-06-16 10:54:58 +00:00
|
|
|
if osm_domain not in url:
|
|
|
|
return None, None, None
|
|
|
|
if '#map=' not in url:
|
2022-05-21 11:36:53 +00:00
|
|
|
return None, None, None
|
|
|
|
|
2022-06-16 10:54:58 +00:00
|
|
|
coords_str = url.split('#map=')[1]
|
2022-05-21 11:36:53 +00:00
|
|
|
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]
|
2022-05-21 12:23:29 +00:00
|
|
|
if not is_float(latitude):
|
2022-05-21 11:36:53 +00:00
|
|
|
return None, None, None
|
|
|
|
longitude = coords[2]
|
2022-05-21 12:23:29 +00:00
|
|
|
if not is_float(longitude):
|
2022-05-21 11:36:53 +00:00
|
|
|
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
|
|
|
|
"""
|
2022-06-05 12:15:02 +00:00
|
|
|
if '/maps/' not in url:
|
2022-05-21 11:36:53 +00:00
|
|
|
return None, None, None
|
2022-06-05 12:15:02 +00:00
|
|
|
coords_str = url.split('/maps', 1)[1]
|
|
|
|
if '/@' not in coords_str:
|
|
|
|
return None, None, None
|
|
|
|
|
|
|
|
coords_str = coords_str.split('/@', 1)[1]
|
|
|
|
if 'z' not in coords_str:
|
|
|
|
return None, None, None
|
|
|
|
coords_str = coords_str.split('z', 1)[0]
|
2022-05-21 11:36:53 +00:00
|
|
|
|
|
|
|
if ',' not in coords_str:
|
|
|
|
return None, None, None
|
|
|
|
|
|
|
|
coords = coords_str.split(',')
|
|
|
|
if len(coords) != 3:
|
|
|
|
return None, None, None
|
2022-06-05 12:15:02 +00:00
|
|
|
zoom = coords[2]
|
2022-05-21 11:36:53 +00:00
|
|
|
if not zoom.isdigit():
|
|
|
|
return None, None, None
|
|
|
|
latitude = coords[0]
|
2022-05-21 12:23:29 +00:00
|
|
|
if not is_float(latitude):
|
2022-05-21 11:36:53 +00:00
|
|
|
return None, None, None
|
|
|
|
longitude = coords[1]
|
2022-05-21 12:23:29 +00:00
|
|
|
if not is_float(longitude):
|
2022-05-21 11:36:53 +00:00
|
|
|
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]
|
2022-05-21 12:23:29 +00:00
|
|
|
if not is_float(latitude):
|
2022-05-21 11:36:53 +00:00
|
|
|
return None, None, None
|
|
|
|
longitude = coords[1]
|
2022-05-21 12:23:29 +00:00
|
|
|
if not is_float(longitude):
|
2022-05-21 11:36:53 +00:00
|
|
|
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]
|
2022-05-21 12:23:29 +00:00
|
|
|
if not is_float(latitude):
|
2022-05-21 11:36:53 +00:00
|
|
|
return None, None, None
|
|
|
|
longitude = coords[1]
|
2022-05-21 12:23:29 +00:00
|
|
|
if not is_float(longitude):
|
2022-05-21 11:36:53 +00:00
|
|
|
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]
|
2022-05-21 12:23:29 +00:00
|
|
|
if not is_float(latitude):
|
2022-05-21 11:36:53 +00:00
|
|
|
return None, None, None
|
|
|
|
longitude = coords[1]
|
2022-05-21 12:23:29 +00:00
|
|
|
if not is_float(longitude):
|
2022-05-21 11:36:53 +00:00
|
|
|
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
|
|
|
|
|
|
|
|
|
2022-05-22 14:15:04 +00:00
|
|
|
def geocoords_from_map_link(url: str,
|
|
|
|
osm_domain: str = 'openstreetmap.org') -> (int,
|
|
|
|
float,
|
|
|
|
float):
|
2022-05-21 11:36:53 +00:00
|
|
|
"""Returns geocoordinates from a map link url
|
|
|
|
"""
|
|
|
|
if osm_domain in url:
|
|
|
|
return _geocoords_from_osm_link(url, osm_domain)
|
2022-05-30 15:15:17 +00:00
|
|
|
if '.google.co' in url:
|
2022-05-21 11:36:53 +00:00
|
|
|
return _geocoords_from_gmaps_link(url)
|
2022-05-30 15:15:17 +00:00
|
|
|
if '.bing.co' in url:
|
2022-05-21 11:36:53 +00:00
|
|
|
return _geocoords_from_bmaps_link(url)
|
2022-05-30 15:15:17 +00:00
|
|
|
if '.waze.co' in url:
|
2022-05-21 11:36:53 +00:00
|
|
|
return _geocoords_from_waze_link(url)
|
2022-05-30 15:15:17 +00:00
|
|
|
if 'wego.here.co' in url:
|
2022-05-21 11:36:53 +00:00
|
|
|
return _geocoords_from_wego_link(url)
|
|
|
|
return None, None, None
|
|
|
|
|
|
|
|
|
|
|
|
def html_open_street_map(url: str,
|
|
|
|
bounding_box_degrees: float,
|
2022-05-23 13:36:15 +00:00
|
|
|
translate: {},
|
|
|
|
width: str = "725",
|
|
|
|
height: str = "650") -> str:
|
2022-05-21 11:36:53 +00:00
|
|
|
"""Returns embed html for an OSM link
|
|
|
|
"""
|
|
|
|
osm_domain = 'openstreetmap.org'
|
2022-05-22 12:37:57 +00:00
|
|
|
zoom, latitude, longitude = geocoords_from_map_link(url, osm_domain)
|
2022-05-21 11:36:53 +00:00
|
|
|
if not latitude:
|
|
|
|
return ''
|
|
|
|
if not longitude:
|
|
|
|
return ''
|
|
|
|
if not zoom:
|
|
|
|
return ''
|
|
|
|
|
|
|
|
html_str = \
|
2022-05-23 13:36:15 +00:00
|
|
|
'<iframe width="' + width + '" height="' + height + \
|
|
|
|
'" frameborder="0" ' + \
|
2022-05-21 11:36:53 +00:00
|
|
|
'scrolling="no" marginheight="0" marginwidth="0" ' + \
|
|
|
|
'src="https://www.' + osm_domain + '/export/embed.html?' + \
|
|
|
|
'bbox=' + str(longitude - bounding_box_degrees) + \
|
|
|
|
'%2C' + \
|
|
|
|
str(latitude - bounding_box_degrees) + \
|
|
|
|
'%2C' + \
|
|
|
|
str(longitude + bounding_box_degrees) + \
|
|
|
|
'%2C' + \
|
|
|
|
str(latitude + bounding_box_degrees) + \
|
|
|
|
'&layer=mapnik" style="border: 1px solid black"></iframe>' + \
|
|
|
|
'<br/><small><a href="https://www.' + osm_domain + '/#map=' + \
|
2022-05-21 12:26:58 +00:00
|
|
|
str(zoom) + '/' + str(latitude) + '/' + str(longitude) + \
|
2022-05-21 11:36:53 +00:00
|
|
|
'">' + translate['View Larger Map'] + '</a></small>\n'
|
|
|
|
return html_str
|
2022-05-22 12:37:57 +00:00
|
|
|
|
|
|
|
|
|
|
|
def set_map_preferences_url(base_dir: str, nickname: str, domain: str,
|
|
|
|
maps_website_url: str) -> None:
|
|
|
|
"""Sets the preferred maps website for an account
|
|
|
|
"""
|
|
|
|
maps_filename = \
|
|
|
|
acct_dir(base_dir, nickname, domain) + '/map_preferences.json'
|
|
|
|
if os.path.isfile(maps_filename):
|
|
|
|
maps_json = load_json(maps_filename)
|
|
|
|
maps_json['url'] = maps_website_url
|
|
|
|
else:
|
|
|
|
maps_json = {
|
|
|
|
'url': maps_website_url
|
|
|
|
}
|
|
|
|
save_json(maps_json, maps_filename)
|
|
|
|
|
|
|
|
|
|
|
|
def get_map_preferences_url(base_dir: str, nickname: str, domain: str) -> str:
|
|
|
|
"""Gets the preferred maps website for an account
|
|
|
|
"""
|
|
|
|
maps_filename = \
|
|
|
|
acct_dir(base_dir, nickname, domain) + '/map_preferences.json'
|
|
|
|
if os.path.isfile(maps_filename):
|
|
|
|
maps_json = load_json(maps_filename)
|
|
|
|
if maps_json.get('url'):
|
|
|
|
return maps_json['url']
|
|
|
|
return None
|
|
|
|
|
|
|
|
|
|
|
|
def set_map_preferences_coords(base_dir: str, nickname: str, domain: str,
|
|
|
|
latitude: float, longitude: float,
|
|
|
|
zoom: int) -> None:
|
|
|
|
"""Sets the preferred maps website coordinates for an account
|
|
|
|
"""
|
|
|
|
maps_filename = \
|
|
|
|
acct_dir(base_dir, nickname, domain) + '/map_preferences.json'
|
|
|
|
if os.path.isfile(maps_filename):
|
|
|
|
maps_json = load_json(maps_filename)
|
|
|
|
maps_json['latitude'] = latitude
|
|
|
|
maps_json['longitude'] = longitude
|
|
|
|
maps_json['zoom'] = zoom
|
|
|
|
else:
|
|
|
|
maps_json = {
|
|
|
|
'latitude': latitude,
|
|
|
|
'longitude': longitude,
|
|
|
|
'zoom': zoom
|
|
|
|
}
|
|
|
|
save_json(maps_json, maps_filename)
|
|
|
|
|
|
|
|
|
|
|
|
def get_map_preferences_coords(base_dir: str,
|
|
|
|
nickname: str,
|
|
|
|
domain: str) -> (float, float, int):
|
|
|
|
"""Gets the preferred maps website coordinates for an account
|
|
|
|
"""
|
|
|
|
maps_filename = \
|
|
|
|
acct_dir(base_dir, nickname, domain) + '/map_preferences.json'
|
|
|
|
if os.path.isfile(maps_filename):
|
|
|
|
maps_json = load_json(maps_filename)
|
|
|
|
if maps_json.get('latitude') and \
|
|
|
|
maps_json.get('longitude') and \
|
|
|
|
maps_json.get('zoom'):
|
|
|
|
return maps_json['latitude'], \
|
|
|
|
maps_json['longitude'], \
|
|
|
|
maps_json['zoom']
|
|
|
|
return None, None, None
|