main.py 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189
  1. from flask import Flask, request, send_file, jsonify, make_response
  2. from flask_cors import CORS
  3. import jwt
  4. from images_manipulator import PngFile, SvgFile, JpgFile
  5. from dotenv import load_dotenv
  6. from functools import wraps
  7. import os
  8. load_dotenv()
  9. import tempfile
  10. app = Flask(__name__)
  11. app.config.update(SECRET_KEY=os.environ.get('SECRET_KEY'))
  12. USERS = os.environ.get('USERS').split(',')
  13. CORS(app)
  14. # Authentication decorator
  15. def token_required(f):
  16. @wraps(f)
  17. def decorator(*args, **kwargs):
  18. token = None
  19. # ensure the jwt-token is passed with the headers
  20. if 'x-access-token' in request.headers:
  21. token = request.headers['x-access-token']
  22. if not token: # throw error if no token provided
  23. return make_response(jsonify({"message": "A valid token is missing!"}), 401)
  24. try:
  25. # decode the token to obtain user public_id
  26. data = jwt.decode(
  27. token, app.config['SECRET_KEY'], algorithms=['HS256'])
  28. if not data['aktivisda_user'] in USERS:
  29. return make_response(jsonify({"message": "Invalid token!"}), 401)
  30. app.logger.info(f'Request { f.__name__} for user { data["aktivisda_user"]}')
  31. except Exception as e:
  32. return make_response(jsonify({"message": "Invalid token!"}), 401)
  33. # Return the user information attached to the token
  34. return f(*args, **kwargs)
  35. return decorator
  36. @app.route('/', methods=['GET'])
  37. def hello_world():
  38. return "hello world"
  39. @app.route("/vectorize", methods=['POST'])
  40. @token_required
  41. def vectorize():
  42. if request.method == 'POST':
  43. f = request.files['image']
  44. assert f.filename.endswith('.png')
  45. tempfilename = tempfile.NamedTemporaryFile(delete=True, suffix='.png').name
  46. f.save(tempfilename)
  47. png_file = PngFile(tempfilename)
  48. png_file._is_temporary_file = True
  49. nb_colors = int(request.args.get('nb_colors', 1))
  50. white_is_alpha = request.args.get('white_is_alpha', 'false') == 'true'
  51. svg_file = png_file.to_svg(nb_colors=nb_colors, white_is_alpha=white_is_alpha)
  52. svg_file._is_temporary_file = False
  53. svg_file.format_colors()
  54. return send_file(svg_file.filepath, mimetype='image/svg+xml')
  55. @app.route("/canonize", methods=['POST'])
  56. @token_required
  57. def canonize():
  58. if request.method == 'POST':
  59. f = request.files['image']
  60. assert f.filename.endswith('.svg')
  61. tempfilename = tempfile.NamedTemporaryFile(delete=True, suffix='.svg').name
  62. f.save(tempfilename)
  63. svg_file = SvgFile(tempfilename)
  64. svg_file._is_temporary_file = True
  65. svg_file.canonize()
  66. return send_file(svg_file.filepath, mimetype='image/svg+xml')
  67. @app.route("/posterize", methods=['POST'])
  68. @token_required
  69. def posterize():
  70. if request.method == 'POST':
  71. f = request.files['image']
  72. assert f.filename.endswith('.png')
  73. tempfilename = tempfile.NamedTemporaryFile(delete=True, suffix='.png').name
  74. f.save(tempfilename)
  75. png_file = PngFile(tempfilename)
  76. png_file._is_temporary_file = True
  77. nb_colors = int(request.args.get('nb_colors', 1))
  78. white_is_alpha = request.args.get('white_is_alpha', 'false') == 'true'
  79. posterized_file = png_file.posterize(nb_colors=nb_colors, white_is_alpha=white_is_alpha)[0]
  80. return send_file(posterized_file.filepath, mimetype='image/png')
  81. @app.route("/hitform", methods=['POST'])
  82. @token_required
  83. def hitpath():
  84. if request.method == 'POST':
  85. f = request.files['image']
  86. assert f.filename.endswith('.svg')
  87. tempfilename = tempfile.NamedTemporaryFile(delete=True, suffix='.svg').name
  88. f.save(tempfilename)
  89. svg_file = SvgFile(tempfilename)
  90. svg_file._is_temporary_file = True
  91. hitpath = svg_file.compute_hitpath()
  92. return jsonify(hitpath=hitpath)
  93. @app.route("/hull", methods=['POST'])
  94. @token_required
  95. def hull():
  96. if request.method == 'POST':
  97. hull = request.files['image']
  98. assert hull.filename.endswith('.svg')
  99. tempfilename = tempfile.NamedTemporaryFile(delete=True, suffix='.svg').name
  100. hull.save(tempfilename)
  101. svg_file = SvgFile(tempfilename)
  102. svg_file.canonize()
  103. hull = svg_file.compute_hull()
  104. return jsonify(hull=hull)
  105. @app.route("/preview", methods=['POST'])
  106. @token_required
  107. def preview():
  108. if request.method == 'POST':
  109. image = request.files['image']
  110. extension = os.path.splitext(image.filename)[1]
  111. tempfilename = tempfile.NamedTemporaryFile(delete=True, suffix=extension).name
  112. image.save(tempfilename)
  113. if extension == '.svg':
  114. svg_file = SvgFile(tempfilename)
  115. png_file = svg_file.to_png(minimum_size=120)
  116. png_file.compress()
  117. return send_file(png_file.filepath, mimetype='image/png')
  118. elif extension == '.jpg':
  119. jpg_file = JpgFile(tempfilename)
  120. jpg_file.resize(120, 120)
  121. jpg_file.compress()
  122. return send_file(jpg_file.filepath, mimetype='image/jpg')
  123. elif extension == '.png':
  124. png_file = PngFile(tempfilename)
  125. png_file.resize(120, 120)
  126. png_file.compress()
  127. return send_file(png_file.filepath, mimetype='image/png')
  128. return make_response(jsonify({"message": f"Unknown file extension { extension }"}), 400)
  129. @app.route("/thumbnail", methods=['POST'])
  130. @token_required
  131. def thumbnail():
  132. if request.method == 'POST':
  133. png = request.files['image']
  134. assert png.filename.endswith('.png')
  135. tempfilename = tempfile.NamedTemporaryFile(delete=True, suffix='.png').name
  136. png.save(tempfilename)
  137. png_file = PngFile(tempfilename)
  138. webp_file = png_file.to_webp(width=100, height=110)
  139. # webp_file.compress()
  140. return send_file(webp_file.filepath, mimetype='image/webp')