RXSM update server
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.
This repo is archived. You can view files and clone it, but cannot push or open issues/pull-requests.

116 lines
4.4KB

  1. # Created 2019-09-10 by NGnius
  2. from flask import Flask, Blueprint, jsonify, request, send_file, render_template
  3. import sqlite3 as dblib
  4. from hashlib import sha512
  5. from os import getcwd
  6. from threading import get_ident
  7. from time import time
  8. from datetime import datetime
  9. database_path = 'rxsm-update.db'
  10. database_connections = dict()
  11. app = Flask('rxsm-update-server')
  12. def get_or_create_connection():
  13. global database_connections, database_path
  14. thread_id = get_ident()
  15. if thread_id not in database_connections:
  16. database_connections[thread_id] = dblib.connect(database_path)
  17. return database_connections[thread_id]
  18. @app.route('/', methods=['GET'])
  19. def index():
  20. return render_template('index.html')
  21. @app.route('/release', methods=['POST'])
  22. def create_or_modify_release():
  23. try:
  24. req_json = request.get_json(force=True)
  25. token = req_json['token']
  26. version = req_json['version']
  27. platform = req_json['platform']
  28. url = req_json['url']
  29. except:
  30. return jsonify({'status':400, 'reason':'Invalid request; missing parameter or invalid JSON'}), 400
  31. with open('.token', 'r') as f:
  32. master_token = f.read()
  33. if sha512(token.encode()).hexdigest() != master_token:
  34. return jsonify({'status':403, 'reason':'Permission denied; invalid token'}), 403
  35. db_connection = get_or_create_connection()
  36. cursor = db_connection.cursor()
  37. cursor.execute('SELECT version FROM releases WHERE version=? AND platform=?', (version, platform))
  38. result = cursor.fetchone()
  39. operation = ''
  40. if result is None:
  41. cursor.execute('INSERT INTO releases (version, platform, url, created_date) VALUES (?,?,?,?)', (version, platform, url, int(time())))
  42. operation = 'create'
  43. else:
  44. cursor.execute('UPDATE releases SET url=?, created_date=? WHERE version=? and platform=?', (url, int(time()), version, platform))
  45. operation = 'update'
  46. db_connection.commit()
  47. return jsonify({'status':200, 'reason':'Version %s %sd successfully' % (version, operation)}), 200
  48. @app.route('/db', methods=['GET'])
  49. @app.route('/database', methods=['GET'])
  50. def download_database():
  51. return send_file(database_path, cache_timeout=1, as_attachment=True, attachment_filename='rxsm.sqlite')
  52. @app.route('/update', methods=['POST'])
  53. @app.route('/check-for-update', methods=['POST'])
  54. def check_for_update():
  55. start = time()
  56. db_connection = get_or_create_connection()
  57. cursor = db_connection.cursor()
  58. collect_anonymous_stats = str(request.headers.get('DNT')).strip() != '1'
  59. # hit counter
  60. if collect_anonymous_stats:
  61. today = datetime.today().date().isoformat()
  62. cursor.execute('SELECT count FROM hits WHERE date=?', (today,))
  63. result = cursor.fetchone()
  64. if result is not None:
  65. cursor.execute('UPDATE hits SET count=count+1 WHERE date=?', (today,))
  66. else:
  67. cursor.execute('INSERT INTO hits (date, count) VALUES (?,?)', (today, 1))
  68. db_connection.commit()
  69. # update lookup
  70. try:
  71. req_json = request.get_json(force=True)
  72. current_version = req_json['version']
  73. platform = req_json['platform']
  74. except:
  75. return jsonify({'status':400, 'reason':'Invalid request; missing parameter or invalid JSON'}), 400
  76. cursor.execute('SELECT version, url FROM releases WHERE platform=? ORDER BY created_date DESC', (platform,))
  77. result = cursor.fetchone()
  78. if result is None:
  79. return jsonify({'status':404, 'reason':'Platform not found (%ss)' % (time()-start), 'url':'', 'out-of-date':False}), 404
  80. elif result[0] != current_version:
  81. return jsonify({'status':200, 'reason':'Ok (%ss)' % (time()-start), 'url':result[1], 'out-of-date':True}), 200
  82. else:
  83. return jsonify({'status':200, 'reason':'Ok (%ss)' % (time()-start), 'url':result[1], 'out-of-date':False}), 200
  84. # always try to create db table(s)
  85. conn = get_or_create_connection()
  86. cursor = conn.cursor()
  87. cursor.execute(\
  88. '''CREATE TABLE IF NOT EXISTS releases (
  89. id INTEGER PRIMARY KEY,
  90. version TEXT UNIQUE NOT NULL,
  91. url TEXT NOT NULL,
  92. platform TEXT NOT NULL,
  93. created_date INTEGER NOT NULL
  94. )''' )
  95. cursor.execute(\
  96. '''CREATE TABLE IF NOT EXISTS hits (
  97. date TEXT UNIQUE NOT NULL,
  98. count INTEGER NOT NULL
  99. )''' )
  100. conn.commit()
  101. if __name__ == '__main__':
  102. print('Working directory: ' + getcwd())
  103. app.run(host='0.0.0.0', port=9080, threaded=True)