epicyon/maps.py

325 lines
9.8 KiB
Python

__filename__ = "maps.py"
__author__ = "Bob Mottram"
__license__ = "AGPL3+"
__version__ = "1.3.0"
__maintainer__ = "Bob Mottram"
__email__ = "bob@libreserver.org"
__status__ = "Production"
__module_group__ = "Core"
import os
from utils import is_float
from utils import acct_dir
from utils import load_json
from utils import save_json
def _geocoords_from_osm_link(url: str, osm_domain: str) -> (int, float, float):
"""Returns geocoordinates from an OSM map link
"""
if osm_domain not in url:
return None, None, None
if '#map=' not in url:
return None, None, None
coords_str = url.split('#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 is_float(latitude):
return None, None, None
longitude = coords[2]
if not is_float(longitude):
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)[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]
if ',' not in coords_str:
return None, None, None
coords = coords_str.split(',')
if len(coords) != 3:
return None, None, None
zoom = coords[2]
if not zoom.isdigit():
return None, None, None
latitude = coords[0]
if not is_float(latitude):
return None, None, None
longitude = coords[1]
if not is_float(longitude):
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 is_float(latitude):
return None, None, None
longitude = coords[1]
if not is_float(longitude):
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 is_float(latitude):
return None, None, None
longitude = coords[1]
if not is_float(longitude):
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 is_float(latitude):
return None, None, None
longitude = coords[1]
if not is_float(longitude):
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 = 'openstreetmap.org') -> (int,
float,
float):
"""Returns geocoordinates from a map link url
"""
if osm_domain in url:
return _geocoords_from_osm_link(url, osm_domain)
if '.google.co' in url:
return _geocoords_from_gmaps_link(url)
if '.bing.co' in url:
return _geocoords_from_bmaps_link(url)
if '.waze.co' in url:
return _geocoords_from_waze_link(url)
if '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: {},
width: str = "725",
height: str = "650") -> 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 = \
'<iframe width="' + width + '" height="' + height + \
'" frameborder="0" ' + \
'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) + \
'&amp;layer=mapnik" style="border: 1px solid black"></iframe>' + \
'<br/><small><a href="https://www.' + osm_domain + '/#map=' + \
str(zoom) + '/' + str(latitude) + '/' + str(longitude) + \
'">' + translate['View Larger Map'] + '</a></small>\n'
return html_str
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