-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathdeparture_check.py
More file actions
117 lines (98 loc) · 3.6 KB
/
Copy pathdeparture_check.py
File metadata and controls
117 lines (98 loc) · 3.6 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
116
117
#!/usr/bin/env python3
import os
import sys
import requests
from datetime import datetime, timezone
from rtt import RTT_BASE, get_auth_headers
discord_webhook = os.environ.get("DISCORD_WEBHOOK_URL")
refresh_token = os.environ.get("RTT_REFRESH_TOKEN")
from_crs = os.environ.get("FROM_CRS", "").upper()
to_crs = os.environ.get("TO_CRS", "").upper()
from_name = os.environ.get("FROM_NAME") or from_crs
to_name = os.environ.get("TO_NAME") or to_crs
for name, val in [
("DISCORD_WEBHOOK_URL", discord_webhook),
("RTT_REFRESH_TOKEN", refresh_token),
("FROM_CRS", from_crs),
("TO_CRS", to_crs),
]:
if not val:
print(f"Error: {name} is not set.")
sys.exit(1)
try:
auth = get_auth_headers(refresh_token)
except RuntimeError as e:
print(f"Error: {e}")
sys.exit(1)
# --- Fetch departures ---
print(f"Fetching departures: {from_name} ({from_crs}) → {to_name} ({to_crs})...")
r = requests.get(
f"{RTT_BASE}/gb-nr/location",
params={"code": from_crs, "filterTo": to_crs},
headers=auth,
timeout=10,
)
if r.status_code != 200:
print(f"Error: Failed to fetch departure data. HTTP {r.status_code}")
sys.exit(1)
services = r.json().get("services") or []
if not services:
print(f"No upcoming services found from {from_name} to {to_name}.")
sys.exit(0)
print(f"Found {len(services)} service(s). Building notification...")
fields = []
for service in services[:3]:
meta = service.get("scheduleMetadata", {})
identity = meta.get("identity", "?")
dep_date = meta.get("departureDate", "")
departure = service.get("temporalData", {}).get("departure", {})
sched_dep = departure.get("scheduleAdvertised", "")
if not sched_dep:
continue
rt_dep = departure.get("realtimeForecast") or sched_dep
platform_data = service.get("locationMetadata", {}).get("platform") or {}
platform = platform_data.get("actual") or platform_data.get("planned") or "TBC"
sched_fmt = sched_dep[11:16]
rt_fmt = rt_dep[11:16]
# Fetch full service to get arrival time at the destination stop
detail = requests.get(
f"{RTT_BASE}/gb-nr/service",
params={"identity": identity, "departureDate": dep_date},
headers=auth,
timeout=10,
)
if detail.status_code != 200:
continue
arrival = None
locations = detail.json().get("service", {}).get("locations") or []
for loc in locations:
if to_crs in (loc.get("location", {}).get("shortCodes") or []):
arr = loc.get("temporalData", {}).get("arrival") or {}
arr_time = arr.get("realtimeActual") or arr.get("realtimeForecast") or arr.get("scheduleAdvertised")
if arr_time:
arrival = arr_time[11:16]
break
dep_label = f"~~{sched_fmt}~~ → {rt_fmt}" if rt_fmt != sched_fmt else sched_fmt
fields.append({
"name": f"Departs {dep_label}",
"value": f"Platform {platform} · Arrives {arrival or 'Unknown'}",
"inline": True,
})
if not fields:
print("Error: Could not retrieve details for any services.")
sys.exit(1)
timestamp = datetime.now(timezone.utc).strftime("%Y-%m-%dT%H:%M:%SZ")
payload = {
"embeds": [{
"title": f"🚂 {from_name} → {to_name}",
"color": 3447003,
"fields": fields,
"timestamp": timestamp,
"footer": {"text": "National Rail · Realtime Trains"},
}]
}
r = requests.post(discord_webhook, json=payload, timeout=10)
if r.status_code not in (200, 204):
print(f"Error sending Discord notification. HTTP {r.status_code}")
sys.exit(1)
print(f"Discord notification sent ({len(fields)} train(s) shown).")