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.

112 lines
4.3KB

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