-
Notifications
You must be signed in to change notification settings - Fork 1
/
__init__.py
105 lines (89 loc) Β· 3.74 KB
/
__init__.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
"""Generate optimized images to be served from Google Cloud CDN."""
from typing import Optional
from fastapi import APIRouter, Query
from fastapi.responses import JSONResponse
from clients import images
from config import settings
from database.schemas import PostUpdate
from log import LOGGER
router = APIRouter(prefix="/images", tags=["images"])
@router.post(
"/",
summary="Optimize single post image.",
description="Generate retina and mobile feature_image for a single post upon update.",
)
async def optimize_post_image(post_update: PostUpdate) -> JSONResponse:
"""
Generate retina version of a post's feature image if one doesn't exist.
:param PostUpdate post_update: Incoming payload for an updated Ghost post.
:returns: JSONResponse
"""
new_images = []
post = post_update.post.current
feature_image = post.feature_image
title = post.title
if feature_image:
new_images.append(images.create_retina_image(feature_image))
new_images.append(images.create_mobile_image(feature_image))
new_images = [image for image in new_images if image is not None]
if bool(new_images):
LOGGER.info(f"Generated {len(new_images)} images for post `{title}`: {new_images}")
return JSONResponse(new_images)
return JSONResponse({post.title: "Retina & mobile images already exist"})
return JSONResponse({post.title: "No images exist for optimization"})
@router.get(
"/",
summary="Batch optimize CDN images.",
description="Generates retina and mobile varieties of post feature_images. \
Defaults to images uploaded within the current month; \
accepts a `?directory=` parameter which accepts a path to recursively optimize images on the given CDN.",
)
async def bulk_transform_images(
directory: Optional[str] = Query(
default=None,
title="directory",
description="Subdirectory of remote CDN to transverse and transform images.",
max_length=50,
)
) -> JSONResponse:
"""
Apply transformations to images uploaded within the current month.
Optionally accepts a `directory` parameter to override image directory.
:param Optional[str] directory: Remote directory to recursively fetch images and apply transformations.
:returns: JSONResponse
"""
try:
if directory is None:
directory = settings.GCP_BUCKET_FOLDER
transformed_images = {
"purged": images.purge_unwanted_images(directory),
"retina": images.retina_transformations(directory),
"mobile": images.mobile_transformations(directory),
# "standard": gcs.standard_transformations(directory),
}
response = []
for k, v in transformed_images.items():
if v is not None:
response.append(f"{len(v)} {k}")
else:
response.append(f"0 {k}")
LOGGER.success(f"Transformed {', '.join(response)} images")
return JSONResponse(transformed_images)
except Exception as e:
LOGGER.error(f"Unexpected exception raised when transforming images: {e}")
return JSONResponse(e, status_code=500)
@router.get("/sort/")
async def bulk_organize_images(directory: Optional[str] = None) -> JSONResponse:
"""
Sort retina and mobile images into their appropriate directories.
:param Optional[str] directory: Remote directory to organize images into subdirectories.
:returns: JSONResponse
"""
if directory is None:
directory = settings.GCP_BUCKET_FOLDER
retina_images = images.organize_retina_images(directory)
LOGGER.success(f"Moved {len(retina_images)} retina images.")
return JSONResponse(
{"retina": retina_images},
status_code=200,
)