FlaskAPI.py 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139
  1. import threading
  2. from flask import jsonify
  3. from flask import request
  4. from flask_restful import abort
  5. from core import OrderAnalyser
  6. from core.RestAPI.utils import requires_auth
  7. from core.SynapseLauncher import SynapseLauncher
  8. class FlaskAPI(threading.Thread):
  9. def __init__(self, app, port=5000, brain=None):
  10. """
  11. :param app: Flask API
  12. :param port: Port to listen
  13. :param brain: Brain object
  14. :type brain: Brain
  15. """
  16. super(FlaskAPI, self).__init__()
  17. self.app = app
  18. self.port = port
  19. self.brain = brain
  20. self.app.add_url_rule('/synapses/', view_func=self.get_synapses, methods=['GET'])
  21. self.app.add_url_rule('/synapses/<synapse_name>', view_func=self.get_synapse, methods=['GET'])
  22. self.app.add_url_rule('/synapses/<synapse_name>', view_func=self.run_synapse, methods=['POST'])
  23. self.app.add_url_rule('/order/', view_func=self.run_order, methods=['POST'])
  24. self.app.add_url_rule('/shutdown/', view_func=self.shutdown_server, methods=['POST'])
  25. def run(self):
  26. self.app.run(host='0.0.0.0', port="%s" % int(self.port), debug=True, threaded=True, use_reloader=False)
  27. def _get_synapse_by_name(self, synapse_name):
  28. """
  29. Find a synapse in the brain by its name
  30. :param synapse_name:
  31. :return:
  32. """
  33. all_synapse = self.brain.brain_yaml
  34. for el in all_synapse:
  35. try:
  36. if el["name"] == synapse_name:
  37. return el
  38. except KeyError:
  39. pass
  40. return None
  41. @requires_auth
  42. def get_synapses(self):
  43. """
  44. get all synapse
  45. """
  46. data = jsonify(synapses=self.brain.brain_yaml)
  47. return data, 200
  48. @requires_auth
  49. def get_synapse(self, synapse_name):
  50. """
  51. get a synapse by its name
  52. """
  53. synapse_target = self._get_synapse_by_name(synapse_name)
  54. if synapse_target is not None:
  55. data = jsonify(synapses=synapse_target)
  56. return data, 200
  57. data = {
  58. "synapse name not found": "%s" % synapse_name
  59. }
  60. return jsonify(error=data), 404
  61. @requires_auth
  62. def run_synapse(self, synapse_name):
  63. """
  64. Run a synapse by its name
  65. test with curl:
  66. curl -i --user admin:secret -X POST http://localhost:5000/synapses/say-hello
  67. :param synapse_name:
  68. :return:
  69. """
  70. synapse_target = self._get_synapse_by_name(synapse_name)
  71. if synapse_target is None:
  72. data = {
  73. "synapse name not found": "%s" % synapse_name
  74. }
  75. return jsonify(error=data), 404
  76. # run the synapse
  77. SynapseLauncher.start_synapse(synapse_name, brain=self.brain)
  78. data = jsonify(synapses=synapse_target)
  79. return data, 201
  80. @requires_auth
  81. def run_order(self):
  82. """
  83. Give an order to Kalliope via API like it was from a spoken one
  84. Test with curl
  85. curl -i --user admin:secret -H "Content-Type: application/json" -X POST -d '{"order":"my order"}' http://localhost:5000/order
  86. In case of quotes in the order or accents, use a file
  87. cat post.json:
  88. {"order":"j'aime"}
  89. curl -i --user admin:secret -H "Content-Type: application/json" -X POST --data @post.json http://localhost:5000/order/
  90. :return:
  91. """
  92. if not request.get_json() or 'order' not in request.get_json():
  93. abort(400)
  94. order = request.get_json('order')
  95. if order is not None:
  96. # get the order
  97. order_to_run = order["order"]
  98. oa = OrderAnalyser(order=order_to_run, brain=self.brain)
  99. launched_synapses = oa.start()
  100. if launched_synapses:
  101. # if the list is not empty, we have launched one or more synapses
  102. data = jsonify(synapses=[e.serialize() for e in launched_synapses])
  103. return data, 201
  104. else:
  105. data = {
  106. "error": "The given order doesn't match any synapses"
  107. }
  108. return jsonify(error=data), 400
  109. else:
  110. data = {
  111. "error": "order cannot be null"
  112. }
  113. return jsonify(error=data), 400
  114. @requires_auth
  115. def shutdown_server(self):
  116. func = request.environ.get('werkzeug.server.shutdown')
  117. if func is None:
  118. raise RuntimeError('Not running with the Werkzeug Server')
  119. func()
  120. return "Shutting down..."