diff --git a/apps/njtransit/manifest.yaml b/apps/njtransit/manifest.yaml index 921b070c5..2dd833745 100644 --- a/apps/njtransit/manifest.yaml +++ b/apps/njtransit/manifest.yaml @@ -10,4 +10,4 @@ recommendedInterval: 5 category: transit tags: [] published: '2022-12-06T04:28:51Z' -updated: '2026-06-08T04:46:54Z' +updated: '2026-10-09T00:41:38Z' diff --git a/apps/njtransit/nj_transit.star b/apps/njtransit/nj_transit.star index 67af47635..a2a3400b4 100644 --- a/apps/njtransit/nj_transit.star +++ b/apps/njtransit/nj_transit.star @@ -349,6 +349,10 @@ def render_departure_row(departure): def get_schema(): options = getStationListOptions() + # Keep the schema valid if NJ Transit is unavailable or changes its page data. + if len(options) == 0: + options = [create_option("Station list unavailable", DEFAULT_STATION)] + fields = [ schema.Dropdown( id = "station", @@ -541,26 +545,42 @@ def fetch_stations_from_website(): # The format uses indexed references where objects contain indices pointing to values data = json.decode(json_content) - # Iterate through the data array to find station objects - # Station objects have the pattern: {"__typename": idx1, "title": idx2, "path": idx3} - # where data[idx1] == "TrainScheduleStation" and data[idx2] is the station name + # Find the explicit Departure Vision station collection. Nuxt stores the + # collection, its objects, and their fields as indices into this same array. + dv_stations_idx = None + for item in data: + if type(item) == "dict" and "dvStations" in item: + candidate_idx = item["dvStations"] + if type(candidate_idx) == "int" and candidate_idx >= 0 and candidate_idx < len(data) and type(data[candidate_idx]) == "list": + dv_stations_idx = candidate_idx + break + + if dv_stations_idx == None: + print("Could not find Departure Vision stations in Nuxt data") + return result + stations_found = 0 - for i in range(len(data)): - item = data[i] + stations_seen = {} + for station_idx in data[dv_stations_idx]: + if type(station_idx) != "int" or station_idx < 0 or station_idx >= len(data): + continue + + item = data[station_idx] # Check if this is a dict with the expected station structure - if type(item) == "dict" and "__typename" in item and "title" in item and "path" in item: + if type(item) == "dict" and "__typename" in item and "title" in item: typename_idx = item["__typename"] title_idx = item["title"] # Safely get values by index - if typename_idx < len(data) and title_idx < len(data): + if type(typename_idx) == "int" and type(title_idx) == "int" and typename_idx >= 0 and title_idx >= 0 and typename_idx < len(data) and title_idx < len(data): typename = data[typename_idx] title = data[title_idx] # Check if this is a TrainScheduleStation with a valid title - if typename == "TrainScheduleStation" and type(title) == "string" and len(title) > 0: + if typename == "TrainScheduleStation" and type(title) == "string" and len(title) > 0 and title not in stations_seen: result.append(title) + stations_seen[title] = True stations_found = stations_found + 1 print("Got response of '%s' stations" % stations_found)