Public repository for MUR pre alpha
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

171 lines
5.4 KiB

  1. #!flask/bin/python
  2. import subprocess
  3. import sqlite3
  4. import secrets
  5. from flask import Flask, abort, request, jsonify
  6. START_PORT = 8128
  7. GAME_EXEC = '/opt/godot/Godot_v3.1.1-stable_linux_server.64'
  8. GAME_EXEC_ARG_PACK = '--main-pack'
  9. GAME_EXEC_ARG_PACK_PATH = '/opt/godot/Muffrace Pre Alpha.pck'
  10. GAME_EXEC_ARG_PORT = '--port={0}'
  11. GAME_EXEC_ARG_ID = '--server-id={0}'
  12. GAME_EXEC_ARG_SECRET = '--secret={0}'
  13. GAME_EXEC_ARG_BOTS = '--bots={0}'
  14. games = {}
  15. try:
  16. with sqlite3.connect("database.db") as con:
  17. cur = con.cursor()
  18. cur.execute(
  19. 'CREATE TABLE IF NOT EXISTS games (id INTEGER PRIMARY KEY, name TEXT, secret TEXT, ip TEXT, running INTEGER, port INTEGER, player_count INTEGER, bots INTEGER)')
  20. con.commit()
  21. except:
  22. con.rollback()
  23. finally:
  24. con.close()
  25. app = Flask(__name__)
  26. @app.route('/client/game/create', methods=['POST'])
  27. def create_game():
  28. # TODO: block multiple request from same user
  29. if not request.json:
  30. abort(400)
  31. if not 'name' in request.json:
  32. abort(400)
  33. bots = False
  34. name = request.json.get('name')
  35. if 'bots' in request.json:
  36. bots = request.json.get('bots')
  37. try:
  38. with sqlite3.connect("database.db") as con:
  39. # check free port
  40. port = START_PORT
  41. cur = con.cursor()
  42. cur.execute("SELECT * FROM games WHERE port=?", (port,))
  43. rows = cur.fetchall()
  44. while rows:
  45. port += 1
  46. cur.execute("SELECT * FROM games WHERE port=?", (port,))
  47. rows = cur.fetchall()
  48. # check duplicate name
  49. base_name = name
  50. base_name_count = 1
  51. cur.execute("SELECT * FROM games WHERE name=?", (name,))
  52. rows = cur.fetchall()
  53. while rows:
  54. base_name_count += 1
  55. name = base_name + "_" + str(base_name_count)
  56. cur.execute("SELECT * FROM games WHERE name=?", (name,))
  57. rows = cur.fetchall()
  58. # gen secret
  59. secret = secrets.token_hex(32)
  60. cur.execute("INSERT INTO games (name,secret,ip,port,bots,running) VALUES (?,?,?,?,?,0)",
  61. (name, secret, request.remote_addr, port, bots))
  62. con.commit()
  63. cur.execute("SELECT id FROM games WHERE secret=?",
  64. (secret,))
  65. result = cur.fetchone()
  66. if result[0]:
  67. games[result[0]] = subprocess.Popen([GAME_EXEC, GAME_EXEC_ARG_PACK, GAME_EXEC_ARG_PACK_PATH, GAME_EXEC_ARG_ID.format(int(result[0])), GAME_EXEC_ARG_PORT.format(
  68. port), GAME_EXEC_ARG_SECRET.format(secret), GAME_EXEC_ARG_BOTS.format(int(bots))])
  69. except:
  70. con.rollback()
  71. abort(500)
  72. finally:
  73. con.close()
  74. return jsonify({'name': name, 'port': port})
  75. @app.route('/client/games', methods=['GET'])
  76. def get_games():
  77. try:
  78. with sqlite3.connect("database.db") as con:
  79. cur = con.cursor()
  80. query = "SELECT * FROM games ORDER BY running"
  81. if 'open' in request.args:
  82. query = "SELECT * FROM games WHERE running=0"
  83. cur.execute(query)
  84. rows = cur.fetchall()
  85. except:
  86. con.rollback()
  87. finally:
  88. con.close()
  89. result = []
  90. for row in rows:
  91. result.append(
  92. {'name': row[1], 'player_count': row[6], 'running': (row[4] == 1), 'port': row[5], 'bots': row[7]})
  93. return jsonify(result)
  94. @app.route('/game', methods=['PUT'])
  95. def update_game():
  96. if not request.json:
  97. abort(400)
  98. if not 'secret' in request.json or not 'player_count' in request.json or not 'running' in request.json:
  99. abort(400)
  100. secret = request.json.get('secret')
  101. player_count = request.json.get('player_count')
  102. running = request.json.get('running')
  103. try:
  104. with sqlite3.connect("database.db") as con:
  105. cur = con.cursor()
  106. cur.execute("SELECT id FROM games WHERE secret=?",
  107. (secret,))
  108. result = cur.fetchone()
  109. if result[0]:
  110. game_id = result[0]
  111. cur.execute("UPDATE games SET player_count=?,running=? WHERE id=?",
  112. (player_count, running, game_id,))
  113. con.commit()
  114. else:
  115. abort(401)
  116. except:
  117. con.rollback()
  118. return jsonify(False)
  119. finally:
  120. con.close()
  121. return jsonify(True)
  122. @app.route('/game', methods=['DELETE'])
  123. def close_game():
  124. if not request.json:
  125. abort(400)
  126. if not 'secret' in request.json:
  127. abort(400)
  128. secret = request.json.get('secret')
  129. try:
  130. with sqlite3.connect("database.db") as con:
  131. cur = con.cursor()
  132. cur.execute("SELECT id FROM games WHERE secret=?",
  133. (secret,))
  134. result = cur.fetchone()
  135. if result[0]:
  136. game_id = result[0]
  137. cur.execute("DELETE FROM games WHERE id=?", (game_id,))
  138. con.commit()
  139. if games[game_id]:
  140. games[game_id].terminate()
  141. games[game_id].communicate()
  142. del games[game_id]
  143. else:
  144. abort(401)
  145. except:
  146. con.rollback()
  147. return jsonify(False)
  148. finally:
  149. con.close()
  150. return jsonify(True)
  151. if __name__ == '__main__':
  152. app.run(debug=True)