File size: 1,174 Bytes
1b141db
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
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)