| 
									
										
										
										
											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 |