| from __future__ import annotations |
|
|
| import re |
| from urllib.parse import parse_qs, unquote, urlparse |
|
|
|
|
| COORD_PATTERN = re.compile( |
| r"(?<!\d)([-+]?(?:[0-8]?\d(?:\.\d+)?|90(?:\.0+)?))\s*,\s*" |
| r"([-+]?(?:1[0-7]\d(?:\.\d+)?|[0-9]?\d(?:\.\d+)?|180(?:\.0+)?))(?!\d)" |
| ) |
|
|
|
|
| def parse_lat_lon(text: str | None) -> tuple[float, float] | None: |
| if not text: |
| return None |
| match = COORD_PATTERN.search(text) |
| if not match: |
| return None |
| lat, lon = float(match.group(1)), float(match.group(2)) |
| if -90 <= lat <= 90 and -180 <= lon <= 180: |
| return lat, lon |
| return None |
|
|
|
|
| def extract_coordinates_from_text(text: str | None) -> tuple[float, float] | None: |
| if not text: |
| return None |
| decoded = unquote(text) |
| parsed = urlparse(decoded) |
| query = parse_qs(parsed.query) |
| for key in ("q", "query", "ll"): |
| if key in query: |
| coords = parse_lat_lon(query[key][0]) |
| if coords: |
| return coords |
| at_match = re.search(r"/@(-?\d+(?:\.\d+)?),(-?\d+(?:\.\d+)?)", decoded) |
| if at_match: |
| return float(at_match.group(1)), float(at_match.group(2)) |
| return parse_lat_lon(decoded) |
|
|