From 5a440d9bb322ef1f74763d613e1beefee3f31ea4 Mon Sep 17 00:00:00 2001 From: Matheus Buss Date: Tue, 30 Aug 2022 17:42:07 -0300 Subject: [PATCH 1/3] First implementation of serve_thumb.py --- resize_rich_link_images/.gitignore | 3 ++ resize_rich_link_images/config.yaml | 42 +++++++++++++++ resize_rich_link_images/event.json | 25 +++++++++ resize_rich_link_images/inject_secrets.sh | 8 +++ resize_rich_link_images/pyvenv.cfg | 8 +++ resize_rich_link_images/serve_thumb.py | 63 +++++++++++++++++++++++ 6 files changed, 149 insertions(+) create mode 100644 resize_rich_link_images/.gitignore create mode 100644 resize_rich_link_images/config.yaml create mode 100644 resize_rich_link_images/event.json create mode 100644 resize_rich_link_images/inject_secrets.sh create mode 100644 resize_rich_link_images/pyvenv.cfg create mode 100644 resize_rich_link_images/serve_thumb.py diff --git a/resize_rich_link_images/.gitignore b/resize_rich_link_images/.gitignore new file mode 100644 index 0000000..f412002 --- /dev/null +++ b/resize_rich_link_images/.gitignore @@ -0,0 +1,3 @@ +# created by virtualenv automatically +lib/ +bin/ diff --git a/resize_rich_link_images/config.yaml b/resize_rich_link_images/config.yaml new file mode 100644 index 0000000..c028e4c --- /dev/null +++ b/resize_rich_link_images/config.yaml @@ -0,0 +1,42 @@ +region: us-east-1 + +function_name: resize_rich_link_images +handler: serve_thumb.lambda_handler +description: Serve thumbnail for rich link. If thumbnail does not exist, create it +runtime: python3.9 +# role: lambda_basic_execution + +# S3 upload requires appropriate role with s3:PutObject permission +# (ex. basic_s3_upload), a destination bucket, and the key prefix +# bucket_name: 'example-bucket' +# s3_key_prefix: 'path/to/file/' + +# if access key and secret are left blank, boto will use the credentials +# defined in the [default] section of ~/.aws/credentials. + +# In this project the aws access keys are injected via github actions +# when deploying the lambda function +aws_access_key_id: AWS_ACCESS_KEY_ID +aws_secret_access_key: AWS_SECRET_ACCESS_KEY + +# dist_directory: dist +# timeout: 15 +# memory_size: 512 +# concurrency: 500 +# + +# Experimental Environment variables +# environment_variables: +# env_1: foo +# env_2: baz + +# If `tags` is uncommented then tags will be set at creation or update +# time. During an update all other tags will be removed except the tags +# listed here. +#tags: +# tag_1: foo +# tag_2: bar + +# Build options +build: + source_directories: lib # a comma delimited list of directories in your project root that contains source to package. diff --git a/resize_rich_link_images/event.json b/resize_rich_link_images/event.json new file mode 100644 index 0000000..2aad0c1 --- /dev/null +++ b/resize_rich_link_images/event.json @@ -0,0 +1,25 @@ +{ + "Records": [ + { + "cf": { + "config": { + "distributionId": "EXAMPLE" + }, + "request": { + "uri": "/api/rich_link", + "method": "GET", + "clientIp": "2001:cdba::3257:9652", + "body": "", + "headers": { + "host": [ + { + "key": "Host", + "value": "d123.cf.net" + } + ] + } + } + } + } + ] +} \ No newline at end of file diff --git a/resize_rich_link_images/inject_secrets.sh b/resize_rich_link_images/inject_secrets.sh new file mode 100644 index 0000000..3d80d0b --- /dev/null +++ b/resize_rich_link_images/inject_secrets.sh @@ -0,0 +1,8 @@ +#!/bin/bash + +echo "Injectig AWS keys" + +sed -i "s/AWS_ACCESS_KEY_ID/$1/g" config.yaml +sed -i "s/AWS_SECRET_ACCESS_KEY/$2/g" config.yaml + +echo "Injection complete" diff --git a/resize_rich_link_images/pyvenv.cfg b/resize_rich_link_images/pyvenv.cfg new file mode 100644 index 0000000..ffc88e6 --- /dev/null +++ b/resize_rich_link_images/pyvenv.cfg @@ -0,0 +1,8 @@ +home = /usr +implementation = CPython +version_info = 3.9.13.final.0 +virtualenv = 20.16.3 +include-system-site-packages = false +base-prefix = /usr +base-exec-prefix = /usr +base-executable = /usr/bin/python3.9 diff --git a/resize_rich_link_images/serve_thumb.py b/resize_rich_link_images/serve_thumb.py new file mode 100644 index 0000000..cdf9e79 --- /dev/null +++ b/resize_rich_link_images/serve_thumb.py @@ -0,0 +1,63 @@ +import json +import boto3 +from bs4 import BeautifulSoup +from PIL import Image +from io import BytesIO + + +def get_image_name(html_body): + body = BeautifulSoup(html_body, 'html.parser') + image_tag = body.find('meta', property='og:image') + image_name = image_tag['content'].split('/')[-1] + return image_name + + +def resize_image(image): + sizeX = image.size[0] + sizeY = image.size[1] + if sizeX > 300: + image.thumbnail((299, sizeY)) + + +def create_thumbnail(s3_client, s3_bucket, original_image, path): + image_object = s3_client.get_object( + Bucket=s3_bucket, Key=original_image) + image = Image.open(BytesIO(image_object['Body'].read())) + resize_image(image) + file_object = BytesIO() + image.save(file_object, 'png') + file_object.seek(0) + s3_client.put_object(Body=file_object, Bucket=s3_bucket, + Key=path, ContentType=image_object['ContentType']) + + +def object_exists(s3_client, s3_bucket, path): + try: + s3_client.head_object(Bucket=s3_bucket, Key=path) + return True + except: + return False + + +def lambda_handler(event, context): + + request = event['Records'][0]['cf']['request'] + + if 'api/rich_link' in request['uri']: + s3_bucket = 'cambiatus-uploads' + s3_image_path = 'cambiatus-uploads/' + s3_thumb_path = 'cambiatus-uploads/thumbnails/' + s3_client = boto3.client('s3') + + image_name = get_image_name(request['body']) + + if not object_exists(s3_client, s3_bucket, s3_thumb_path+image_name): + create_thumbnail(s3_client, s3_bucket, s3_image_path + + image_name, s3_thumb_path+image_name) + + body = request['body'].replace(s3_image_path, s3_thumb_path) + + return { + 'statusCode': 200, + 'body': json.dumps(body) + } From 39261bdc1ecae9c4f92f3b09ccae8e3d8ab3b8a9 Mon Sep 17 00:00:00 2001 From: Matheus Buss Date: Fri, 2 Sep 2022 13:32:17 -0300 Subject: [PATCH 2/3] Fixed body output --- resize_rich_link_images/serve_thumb.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/resize_rich_link_images/serve_thumb.py b/resize_rich_link_images/serve_thumb.py index cdf9e79..88eb52d 100644 --- a/resize_rich_link_images/serve_thumb.py +++ b/resize_rich_link_images/serve_thumb.py @@ -55,9 +55,9 @@ def lambda_handler(event, context): create_thumbnail(s3_client, s3_bucket, s3_image_path + image_name, s3_thumb_path+image_name) - body = request['body'].replace(s3_image_path, s3_thumb_path) + request['body'] = request['body'].replace(s3_image_path, s3_thumb_path) return { 'statusCode': 200, - 'body': json.dumps(body) + 'body': json.dumps(request['body']) } From 372725337a73c4c20582ad56a89869ef670e10e7 Mon Sep 17 00:00:00 2001 From: Matheus Buss Date: Fri, 2 Sep 2022 13:36:27 -0300 Subject: [PATCH 3/3] Reformatted according to black library --- resize_rich_link_images/serve_thumb.py | 52 ++++++++++++++------------ 1 file changed, 28 insertions(+), 24 deletions(-) diff --git a/resize_rich_link_images/serve_thumb.py b/resize_rich_link_images/serve_thumb.py index 88eb52d..ead4976 100644 --- a/resize_rich_link_images/serve_thumb.py +++ b/resize_rich_link_images/serve_thumb.py @@ -6,9 +6,9 @@ def get_image_name(html_body): - body = BeautifulSoup(html_body, 'html.parser') - image_tag = body.find('meta', property='og:image') - image_name = image_tag['content'].split('/')[-1] + body = BeautifulSoup(html_body, "html.parser") + image_tag = body.find("meta", property="og:image") + image_name = image_tag["content"].split("/")[-1] return image_name @@ -20,15 +20,18 @@ def resize_image(image): def create_thumbnail(s3_client, s3_bucket, original_image, path): - image_object = s3_client.get_object( - Bucket=s3_bucket, Key=original_image) - image = Image.open(BytesIO(image_object['Body'].read())) + image_object = s3_client.get_object(Bucket=s3_bucket, Key=original_image) + image = Image.open(BytesIO(image_object["Body"].read())) resize_image(image) file_object = BytesIO() - image.save(file_object, 'png') + image.save(file_object, "png") file_object.seek(0) - s3_client.put_object(Body=file_object, Bucket=s3_bucket, - Key=path, ContentType=image_object['ContentType']) + s3_client.put_object( + Body=file_object, + Bucket=s3_bucket, + Key=path, + ContentType=image_object["ContentType"], + ) def object_exists(s3_client, s3_bucket, path): @@ -41,23 +44,24 @@ def object_exists(s3_client, s3_bucket, path): def lambda_handler(event, context): - request = event['Records'][0]['cf']['request'] + request = event["Records"][0]["cf"]["request"] - if 'api/rich_link' in request['uri']: - s3_bucket = 'cambiatus-uploads' - s3_image_path = 'cambiatus-uploads/' - s3_thumb_path = 'cambiatus-uploads/thumbnails/' - s3_client = boto3.client('s3') + if "api/rich_link" in request["uri"]: + s3_bucket = "cambiatus-uploads" + s3_image_path = "cambiatus-uploads/" + s3_thumb_path = "cambiatus-uploads/thumbnails/" + s3_client = boto3.client("s3") - image_name = get_image_name(request['body']) + image_name = get_image_name(request["body"]) - if not object_exists(s3_client, s3_bucket, s3_thumb_path+image_name): - create_thumbnail(s3_client, s3_bucket, s3_image_path + - image_name, s3_thumb_path+image_name) + if not object_exists(s3_client, s3_bucket, s3_thumb_path + image_name): + create_thumbnail( + s3_client, + s3_bucket, + s3_image_path + image_name, + s3_thumb_path + image_name, + ) - request['body'] = request['body'].replace(s3_image_path, s3_thumb_path) + request["body"] = request["body"].replace(s3_image_path, s3_thumb_path) - return { - 'statusCode': 200, - 'body': json.dumps(request['body']) - } + return {"statusCode": 200, "body": json.dumps(request["body"])}