live.py 2.4 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485
  1. import requests, json
  2. from os import getenv
  3. from flask import Flask, request, abort
  4. # consts
  5. metric_map = {
  6. "spots": "free_slots",
  7. "bikes": "avl_bikes",
  8. "capacity": "total_slots",
  9. "location": "coordinates"
  10. }
  11. url = "https://vancouver-ca.smoove.pro/api-public/stations"
  12. #with open('live_dump.json') as f:
  13. # old_data = json.load(f)
  14. # data = old_data
  15. def refresh_data():
  16. # try to get new data
  17. try:
  18. new = requests.get(url)
  19. except requests.exceptions.RequestException:
  20. print("failed to get data")
  21. data = None
  22. else:
  23. data = new.json()["result"]
  24. # init libs
  25. app = Flask(__name__)
  26. # main function to get data from api
  27. def get_bikes(station, metric):
  28. refresh_data()
  29. # if refresh failed, return 404
  30. if not data:
  31. return 502
  32. # find the station
  33. match = False
  34. for each in data:
  35. split = each['name'].split(' ', 1)
  36. id = split[0]
  37. name = split[1]
  38. if station == id or station == name:
  39. match = each
  40. break
  41. # return 404 if no match
  42. if not match:
  43. return 404
  44. if metric == "both":
  45. result = "Spots: " + str(match["avl_bikes"]) + '<br/>'
  46. result += "Bikes: " + str(match["free_slots"])
  47. return result
  48. return(str(match[metric]))
  49. # interprets REST requests at a given location
  50. # you can get /api/station/metric to get just one metric w/o formatting
  51. @app.route('/api/<string:station>/<string:metric>', methods=['GET'])
  52. def get_metric_info(station, metric):
  53. try:
  54. metric_map[metric]
  55. except KeyError:
  56. abort(404, description="Sorry, that metric does not exist")
  57. result = get_bikes(station, metric_map[metric])
  58. if result == 404:
  59. abort(404, description="Sorry, that station does not exist")
  60. elif result == 502:
  61. abort(502, description="Sorry, the API server isn't responding right now")
  62. else:
  63. return result
  64. # interprets REST requests at a given location
  65. # get /api/station (can be a number or name) returns bikes+slots available
  66. @app.route('/api/<string:station>/', methods=['GET'])
  67. def get_station_info(station):
  68. result = get_bikes(station, "both")
  69. if result == 404:
  70. abort(404, description="Sorry, that station does not exist")
  71. elif result == 502:
  72. abort(502, description="Sorry, the API server isn't responding right now")
  73. else:
  74. return result