aboutsummaryrefslogtreecommitdiffstats
path: root/alphabetlearning/resources/s3.py
blob: af367e2ecc24591dae6a4fdbaeb691e5cf77f09b (plain) (blame)
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
import logging
from pathlib import Path
from typing import Sequence

import boto3
from boto3 import Session
from botocore.exceptions import ClientError
from django.conf import settings

from alphabetlearning.resources.utils import _get_pdf_collection_type

logger = logging.getLogger(__name__)


def get_presigned_obj_url(bucket_name, obj_name, expiration=3600) -> str | None:
    client = boto3.client(
        "s3",
        endpoint_url=settings.AWS_S3_ENDPOINT_URL,
        aws_access_key_id=settings.AWS_ACCESS_KEY_ID,
        aws_secret_access_key=settings.AWS_SECRET_ACCESS_KEY,
        region_name=settings.AWS_S3_REGION_NAME,
    )
    try:
        response = client.generate_presigned_url(
            "get_object",
            Params={"Bucket": bucket_name, "Key": obj_name},
            ExpiresIn=expiration,
        )
    except ClientError as e:
        logger.exception("Error generating presigned URL", extra={"error": e})
        return None
    return response


def get_s3_client() -> Session.client:
    return boto3.Session().client(
        "s3",
        endpoint_url=settings.AWS_S3_ENDPOINT_URL,
        aws_access_key_id=settings.AWS_ACCESS_KEY_ID,
        aws_secret_access_key=settings.AWS_SECRET_ACCESS_KEY,
        region_name=settings.AWS_S3_REGION_NAME,
    )


def upload_files_to_s3(files: Sequence, dir_name: str) -> None:
    """
    Generic upload function. Pass "thumbnails" or "pdfuploads" as dir_name to
    dictate the type of file to upload.
    :param files:
    :param dir_name:
    :return:
    """
    s3_client = get_s3_client()
    for file in files:
        logging.info(f"Uploading {file.name} to S3")
        s3_client.upload_fileobj(file, settings.AWS_STORAGE_BUCKET_NAME, f"{dir_name}/{file.name}")


def upload_snapshotted_pages_to_s3(snapshotted_pages) -> bool:
    s3_client = get_s3_client()
    collection_type = _get_pdf_collection_type(snapshotted_pages)
    if collection_type in ["SINGLE_PDF_SINGLE_PAGE", "SINGLE_PDF_MULTI_PAGE"]:
        for img in snapshotted_pages[0]:
            logging.info(f"Uploading {img} to S3")
            s3_client.upload_file(
                img, settings.AWS_STORAGE_BUCKET_NAME, f"snapshotted_pages/{Path(img).name}"
            )
        return True
    if collection_type in ["MULTI_PDF_SINGLE_PAGE", "MULTI_PDF_MULTI_PAGE"]:
        for pdf in snapshotted_pages:
            for img in pdf:
                logging.info(f"Uploading {img} to S3")
                s3_client.upload_file(
                    img, settings.AWS_STORAGE_BUCKET_NAME, f"snapshotted_pages/{Path(img).name}"
                )
        return True
    return False


def upload_to_s3(pdf_files, thumbnail_files, snapshotted_pages) -> bool:
    """

    :param pdf_files: a list of PDF files
    :param thumbnail_files: a list of thumbnail files
    :param snapshotted_pages: a list of snapshotted pages
    :return: True if the files was uploaded, False otherwise
    """
    try:
        upload_files_to_s3(pdf_files, dir_name="pdfuploads")
        upload_files_to_s3(thumbnail_files, dir_name="thumbnails")
        return upload_snapshotted_pages_to_s3(snapshotted_pages)
    except ClientError:
        logging.exception("Error uploading files to S3")
        return False