44
55# # Native # #
66import io
7+ import json
78from typing import Optional , Set
89
910# # Installed # #
1011import uvicorn
11- from fastapi import FastAPI , Response , Query , HTTPException
12+ from fastapi import FastAPI , Response , Query , Depends , HTTPException
1213from starlette .responses import StreamingResponse
1314
1415# # Project # #
@@ -87,13 +88,24 @@ async def endpoint_get_buses(stop_id: int, get_all_buses: bool = False):
8788 return buses_result .dict ()
8889
8990
91+ class MapQueryParams :
92+ def __init__ (
93+ self ,
94+ size_x : int = google_maps_settings .stop_map_default_size_x ,
95+ size_y : int = google_maps_settings .stop_map_default_size_y ,
96+ zoom : int = google_maps_settings .stop_map_default_zoom ,
97+ map_type : GoogleMapRequest .MapTypes = google_maps_settings .stop_map_default_type
98+ ):
99+ self .size_x = size_x
100+ self .size_y = size_y
101+ self .zoom = zoom
102+ self .map_type = map_type
103+
104+
90105@app .get ("/stop/{stop_id}/map" )
91106async def endpoint_get_stop_map (
92107 stop_id : int ,
93- size_x : int = google_maps_settings .stop_map_default_size_x ,
94- size_y : int = google_maps_settings .stop_map_default_size_y ,
95- zoom : int = google_maps_settings .stop_map_default_zoom ,
96- map_type : GoogleMapRequest .MapTypes = google_maps_settings .stop_map_default_type
108+ map_params : MapQueryParams = Depends ()
97109):
98110 """Get a picture of a map with the stop location marked on it."""
99111 stop = await get_stop (stop_id )
@@ -103,16 +115,53 @@ async def endpoint_get_stop_map(
103115 map_request = GoogleMapRequest (
104116 location_x = stop .lat ,
105117 location_y = stop .lon ,
106- size_x = size_x ,
107- size_y = size_y ,
108- zoom = zoom ,
109- map_type = map_type ,
118+ size_x = map_params . size_x ,
119+ size_y = map_params . size_y ,
120+ zoom = map_params . zoom ,
121+ map_type = map_params . map_type ,
110122 tags = [GoogleMapRequest .Tag (location_x = stop .lat , location_y = stop .lon )]
111123 )
112124 map_data = await get_map (map_request )
113125 return StreamingResponse (io .BytesIO (map_data ), media_type = "image/png" )
114126
115127
128+ @app .get ("/stops/map" )
129+ async def endpoint_get_stops_map (
130+ stops_ids : Set [int ] = Query (None , alias = "stop_id" , min_items = 1 , max_items = 35 ),
131+ map_params : MapQueryParams = Depends (),
132+ ):
133+ """Get a picture of a map with the locations of the given stops marked on it.
134+ The marks are labelled in the same order as the given stops ids.
135+
136+ A header "X-Stops-Tags" is returned, being a JSON associating the Stops IDs with the tag label on the map,
137+ with the format: {"<stop id>" : "<tag label>"}
138+ """
139+ stops = await get_stops (stops_ids )
140+
141+ stops_tags = list ()
142+ stops_tags_relation = dict ()
143+ for i , stop in enumerate (stops ):
144+ tag_label = GoogleMapRequest .Tag .get_allowed_labels ()[i ]
145+ tag = GoogleMapRequest .Tag (label = tag_label , location_x = stop .lat , location_y = stop .lon )
146+ stops_tags .append (tag )
147+ stops_tags_relation [stop .stop_id ] = tag_label
148+
149+ map_request = GoogleMapRequest (
150+ size_x = map_params .size_x ,
151+ size_y = map_params .size_y ,
152+ zoom = map_params .zoom ,
153+ map_type = map_params .map_type ,
154+ tags = stops_tags
155+ )
156+ map_data = await get_map (map_request )
157+
158+ return StreamingResponse (
159+ content = io .BytesIO (map_data ),
160+ media_type = "image/png" ,
161+ headers = {"X-Stops-Tags" : json .dumps (stops_tags_relation )}
162+ )
163+
164+
116165@app .get ("/stop/{stop_id}/photo" )
117166async def endpoint_get_stop_photo (
118167 stop_id : int ,
@@ -130,6 +179,8 @@ async def endpoint_get_stop_photo(
130179 size_y = size_y
131180 )
132181 photo_data = await get_photo (photo_request )
182+ if not photo_data :
183+ raise HTTPException (status_code = 404 , detail = "No StreetView photo available for the stop location" )
133184 return StreamingResponse (io .BytesIO (photo_data ), media_type = "image/png" )
134185
135186
0 commit comments