|
| 1 | +import io |
1 | 2 | import urllib.parse |
2 | 3 |
|
3 | 4 | from flask import Blueprint, request, jsonify, abort, url_for, make_response |
4 | 5 | from flask_cors import CORS |
5 | 6 | from sqlalchemy import and_ |
6 | 7 |
|
7 | 8 | from sqlalchemy.orm.exc import NoResultFound |
| 9 | +from sqlalchemy.exc import PendingRollbackError |
8 | 10 |
|
9 | 11 | from appstore.utils import jsonify_app, asset_fallback, generate_image_url, get_access_token, plat_dimensions, HARDWARE_SUPPORT |
10 | 12 | from .models import App, Collection, HomeBanners, Category, db, Release |
11 | 13 | from .settings import config |
12 | 14 | from .image import generate_preview_image |
13 | 15 |
|
| 16 | +from .s3 import upload_asset, download_asset |
| 17 | + |
14 | 18 | parent_app = None |
15 | 19 | api = Blueprint('api', __name__) |
16 | 20 | CORS(api) |
@@ -71,18 +75,44 @@ def apps_by_id(key): |
71 | 75 | @api.route('/apps/id/<key>/preview') |
72 | 76 | def app_image_by_id(key): |
73 | 77 | app = App.query.filter_by(id=key).one_or_none() |
74 | | - screenshots = {} |
75 | | - for hw in ['aplite', 'basalt', 'chalk', 'diorite', 'emery', 'flint']: |
76 | | - if hw in app.asset_collections: |
77 | | - screenshot = app.asset_collections[hw].screenshots[0] |
78 | | - if screenshot: |
79 | | - screenshots[hw] = screenshot |
80 | | - |
81 | | - icon = None |
82 | | - if app.type == 'watchapp': |
83 | | - icon = app.icon_large |
84 | | - png = generate_preview_image(title=app.title, developer=app.developer.name, icon=icon, screenshots=screenshots) |
85 | | - response = make_response(png) |
| 78 | + |
| 79 | + if not app.preview_image: |
| 80 | + # Guess we will have to generate one. |
| 81 | + screenshots = {} |
| 82 | + for hw in ['aplite', 'basalt', 'chalk', 'diorite', 'emery', 'flint']: |
| 83 | + if hw in app.asset_collections: |
| 84 | + screenshot = app.asset_collections[hw].screenshots[0] |
| 85 | + if screenshot: |
| 86 | + screenshots[hw] = screenshot |
| 87 | + |
| 88 | + icon = None |
| 89 | + if app.type == 'watchapp': |
| 90 | + icon = app.icon_large |
| 91 | + png = generate_preview_image(title=app.title, developer=app.developer.name, icon=icon, screenshots=screenshots) |
| 92 | + |
| 93 | + buf = io.BytesIO() |
| 94 | + buf.write(png) |
| 95 | + buf.seek(0) |
| 96 | + # HACK: upload_asset puts this in a print, which is only really valid for actual Files... |
| 97 | + setattr(buf, 'name', "preview.png") |
| 98 | + asset = upload_asset(buf, mime_type = 'image/png', path = config['S3_PREVIEW_PATH']) |
| 99 | + |
| 100 | + app.preview_image = asset |
| 101 | + try: |
| 102 | + db.session.commit() |
| 103 | + except PendingRollbackError: |
| 104 | + # if someone else gets to it at the same time, no big deal |
| 105 | + pass |
| 106 | + |
| 107 | + response = make_response(png) |
| 108 | + response.headers.set('Content-Type', 'image/png') |
| 109 | + return response |
| 110 | + |
| 111 | + # looks like there's a cached version -- grab it! |
| 112 | + buf = io.BytesIO() |
| 113 | + download_asset(app.preview_image, buf, path = config['S3_PREVIEW_PATH']) |
| 114 | + buf.seek(0) |
| 115 | + response = make_response(buf.read()) |
86 | 116 | response.headers.set('Content-Type', 'image/png') |
87 | 117 | return response |
88 | 118 |
|
|
0 commit comments