forked from BasedHardware/omi
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathuber_links.py
More file actions
116 lines (87 loc) · 3.5 KB
/
Copy pathuber_links.py
File metadata and controls
116 lines (87 loc) · 3.5 KB
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
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
from __future__ import annotations
from dataclasses import dataclass
from typing import Iterable
from urllib.parse import quote
UBER_WEB_BASE_URL = "https://m.uber.com/ul/"
UBER_APP_BASE_URL = "uber://"
@dataclass(frozen=True)
class UberLocation:
latitude: float | None = None
longitude: float | None = None
nickname: str | None = None
formatted_address: str | None = None
def has_coordinates(self) -> bool:
return self.latitude is not None and self.longitude is not None
def has_label(self) -> bool:
return bool(self.nickname or self.formatted_address)
@dataclass(frozen=True)
class UberDeepLinks:
web_link: str
app_link: str
def _clean_text(value: str | None) -> str | None:
if value is None:
return None
cleaned = " ".join(value.split())
return cleaned or None
def _normalize_float(value: float | int | str | None) -> float | None:
if value in (None, ""):
return None
return float(value)
def build_location(
*,
latitude: float | int | str | None = None,
longitude: float | int | str | None = None,
nickname: str | None = None,
formatted_address: str | None = None,
) -> UberLocation:
lat = _normalize_float(latitude)
lng = _normalize_float(longitude)
return UberLocation(
latitude=lat,
longitude=lng,
nickname=_clean_text(nickname),
formatted_address=_clean_text(formatted_address),
)
def _append_location_params(params: list[tuple[str, str]], prefix: str, location: UberLocation) -> None:
if location.has_coordinates():
params.append((f"{prefix}[latitude]", str(location.latitude)))
params.append((f"{prefix}[longitude]", str(location.longitude)))
if location.nickname:
params.append((f"{prefix}[nickname]", location.nickname))
if location.formatted_address:
params.append((f"{prefix}[formatted_address]", location.formatted_address))
def _encode_query(params: Iterable[tuple[str, str]]) -> str:
return "&".join(f"{quote(key, safe='[]')}={quote(value, safe='')}" for key, value in params)
def build_uber_deep_links(
*,
destination: str | None = None,
pickup: UberLocation | None = None,
dropoff: UberLocation | None = None,
product_id: str | None = None,
) -> UberDeepLinks:
destination_label = _clean_text(destination)
pickup_location = pickup or UberLocation()
dropoff_location = dropoff or UberLocation()
if destination_label and not dropoff_location.has_label():
dropoff_location = UberLocation(
latitude=dropoff_location.latitude,
longitude=dropoff_location.longitude,
nickname=destination_label,
formatted_address=destination_label,
)
if not destination_label and not dropoff_location.has_label() and not dropoff_location.has_coordinates():
raise ValueError("A destination or dropoff location is required")
params: list[tuple[str, str]] = [("action", "setPickup")]
if pickup_location.has_coordinates() or pickup_location.has_label():
_append_location_params(params, "pickup", pickup_location)
else:
params.append(("pickup", "my_location"))
_append_location_params(params, "dropoff", dropoff_location)
cleaned_product_id = _clean_text(product_id)
if cleaned_product_id:
params.append(("product_id", cleaned_product_id))
query = _encode_query(params)
return UberDeepLinks(
web_link=f"{UBER_WEB_BASE_URL}?{query}",
app_link=f"{UBER_APP_BASE_URL}?{query}",
)