2024-03-01 00:01:00 +00:00
|
|
|
import sys
|
|
|
|
import zipfile
|
2024-02-02 18:36:47 +00:00
|
|
|
from uuid import uuid4
|
2023-11-16 20:13:22 +00:00
|
|
|
|
2024-03-01 00:01:00 +00:00
|
|
|
import alttextbackend.data.analyze as analyze
|
|
|
|
import alttextbackend.data.postgres.books as books
|
|
|
|
import alttextbackend.data.postgres.images as images
|
|
|
|
from django.core.files.base import ContentFile
|
|
|
|
from django.core.files.storage import default_storage
|
|
|
|
from rest_framework import serializers, status
|
|
|
|
from rest_framework.parsers import FormParser, MultiPartParser
|
|
|
|
from rest_framework.response import Response
|
|
|
|
from rest_framework.views import APIView
|
|
|
|
|
|
|
|
sys.path.append("../")
|
|
|
|
|
2023-11-16 20:13:22 +00:00
|
|
|
|
2024-02-09 19:11:31 +00:00
|
|
|
class GetBooksSerializer(serializers.Serializer):
|
|
|
|
titleQ = serializers.CharField(required=False)
|
|
|
|
limit = serializers.IntegerField(min_value=1, required=False)
|
|
|
|
skip = serializers.IntegerField(min_value=0, required=False)
|
2023-11-16 20:13:22 +00:00
|
|
|
|
2024-03-01 00:01:00 +00:00
|
|
|
|
2024-02-09 19:11:31 +00:00
|
|
|
class AddBookSerializer(serializers.Serializer):
|
2024-03-01 00:01:00 +00:00
|
|
|
id = serializers.CharField(required=False)
|
2024-02-09 19:11:31 +00:00
|
|
|
title = serializers.CharField(required=True, allow_blank=False)
|
2024-03-01 00:01:00 +00:00
|
|
|
book = serializers.FileField(required=True)
|
2024-02-09 19:11:31 +00:00
|
|
|
cover = serializers.ImageField(required=False)
|
2023-11-16 20:13:22 +00:00
|
|
|
|
2024-03-01 00:01:00 +00:00
|
|
|
|
2023-11-16 20:13:22 +00:00
|
|
|
class BooksView(APIView):
|
2024-02-02 18:36:47 +00:00
|
|
|
parser_classes = (FormParser, MultiPartParser)
|
2024-02-09 19:11:31 +00:00
|
|
|
serializer_class = AddBookSerializer
|
2024-03-01 00:01:00 +00:00
|
|
|
|
2024-02-09 19:11:31 +00:00
|
|
|
def get_serializer_class(self):
|
2024-03-01 00:01:00 +00:00
|
|
|
if self.request.method == "GET":
|
2024-02-09 19:11:31 +00:00
|
|
|
return GetBooksSerializer
|
2024-03-01 00:01:00 +00:00
|
|
|
elif self.request.method == "POST":
|
2024-02-09 19:11:31 +00:00
|
|
|
return AddBookSerializer
|
|
|
|
return super().get_serializer_class()
|
2024-02-02 18:36:47 +00:00
|
|
|
|
2023-11-16 20:13:22 +00:00
|
|
|
def get(self, request, *args, **kwargs):
|
2024-02-09 19:11:31 +00:00
|
|
|
serializer_class = self.get_serializer_class()
|
|
|
|
serializer = serializer_class(data=request.query_params)
|
|
|
|
if not serializer.is_valid():
|
|
|
|
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
|
|
|
|
|
|
|
|
# Access validated data
|
|
|
|
validated_data = serializer.validated_data
|
2024-03-01 00:01:00 +00:00
|
|
|
titleQ = validated_data.get("titleQ", None)
|
|
|
|
limit = validated_data.get("limit", None)
|
|
|
|
skip = validated_data.get("skip", None)
|
2024-02-09 19:11:31 +00:00
|
|
|
|
2024-03-01 00:01:00 +00:00
|
|
|
# get array of books
|
|
|
|
result = books.getBooks(titleQ, limit, skip)
|
2024-02-09 19:11:31 +00:00
|
|
|
|
2024-03-01 00:01:00 +00:00
|
|
|
return Response(map(books.jsonifyBook, result), status=status.HTTP_200_OK)
|
2023-11-16 20:13:22 +00:00
|
|
|
|
|
|
|
def post(self, request, *args, **kwargs):
|
2024-02-02 18:36:47 +00:00
|
|
|
# validate request data
|
2024-02-09 19:11:31 +00:00
|
|
|
serializer_class = self.get_serializer_class()
|
|
|
|
serializer = serializer_class(data=request.data)
|
2024-02-02 18:36:47 +00:00
|
|
|
if not serializer.is_valid():
|
|
|
|
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
|
|
|
|
validated_data = serializer.validated_data
|
|
|
|
|
2024-03-01 00:01:00 +00:00
|
|
|
id = validated_data.get("id", uuid4())
|
|
|
|
# check if id is already in use
|
|
|
|
book = books.getBook(id)
|
|
|
|
if book:
|
|
|
|
return Response(
|
|
|
|
{"error": "id already in use"}, status=status.HTTP_400_BAD_REQUEST
|
|
|
|
)
|
|
|
|
|
2024-02-02 18:36:47 +00:00
|
|
|
# perform initial book processing
|
2024-03-01 00:01:00 +00:00
|
|
|
file = validated_data["book"]
|
2024-02-02 18:36:47 +00:00
|
|
|
if not file.name.endswith(".zip"):
|
2023-11-16 20:13:22 +00:00
|
|
|
return Response(
|
2024-02-02 18:36:47 +00:00
|
|
|
{"file": ["file must be a zip"]}, status=status.HTTP_400_BAD_REQUEST
|
2023-11-16 20:13:22 +00:00
|
|
|
)
|
2024-03-01 00:01:00 +00:00
|
|
|
book_path = f"./books/{str(id)}"
|
|
|
|
default_storage.save(f"{book_path}.zip", ContentFile(file.read()))
|
|
|
|
with zipfile.ZipFile(default_storage.path(f"{book_path}.zip"), "r") as zip_ref:
|
|
|
|
zip_ref.extractall(default_storage.path(f"{book_path}"))
|
|
|
|
default_storage.delete(f"{book_path}.zip")
|
2023-11-16 20:13:22 +00:00
|
|
|
|
2024-03-01 00:01:00 +00:00
|
|
|
# ensure book has valid root html file
|
|
|
|
html_file = analyze.findHTML(book_path)
|
|
|
|
if html_file == None:
|
|
|
|
default_storage.delete(book_path)
|
|
|
|
return Response(
|
|
|
|
{"error": "No HTML file found in the extracted folder"},
|
|
|
|
status=status.HTTP_400_BAD_REQUEST,
|
|
|
|
)
|
2024-02-08 20:09:34 +00:00
|
|
|
|
2024-02-02 18:36:47 +00:00
|
|
|
# save cover image
|
2024-03-01 00:01:00 +00:00
|
|
|
coverExt = None
|
|
|
|
if "cover" in validated_data and validated_data["cover"] is not None:
|
|
|
|
coverExt = validated_data["cover"].name.split(".")[-1]
|
|
|
|
default_storage.save(
|
|
|
|
f"./covers/{str(id)}.{coverExt}",
|
|
|
|
ContentFile(validated_data["cover"].read()),
|
|
|
|
)
|
|
|
|
|
|
|
|
alt = analyze.createAnalyzer()
|
|
|
|
alt.parseFile(html_file)
|
|
|
|
# store basic book info into database
|
|
|
|
size = analyze.getSize(book_path)
|
|
|
|
imgs = alt.getAllImgs()
|
|
|
|
books.addBook(
|
|
|
|
title=validated_data["title"],
|
|
|
|
size=str(size),
|
|
|
|
numImages=len(imgs),
|
|
|
|
id=id,
|
|
|
|
coverExt=coverExt,
|
2024-02-02 18:36:47 +00:00
|
|
|
)
|
2024-03-01 00:01:00 +00:00
|
|
|
# store info for all images in database
|
|
|
|
for img in imgs:
|
|
|
|
context = alt.getContext(img)
|
|
|
|
thisHash = hash(alt.getImgData(img["src"]))
|
|
|
|
images.addImage(
|
|
|
|
bookid=id,
|
|
|
|
src=img["src"],
|
|
|
|
hash=thisHash,
|
|
|
|
alt=img["alt"],
|
|
|
|
originalAlt=img["alt"],
|
|
|
|
beforeContext=context[0],
|
|
|
|
afterContext=context[1],
|
|
|
|
)
|
2023-11-16 20:13:22 +00:00
|
|
|
|
2024-03-01 00:01:00 +00:00
|
|
|
book = books.getBook(id)
|
2024-02-02 18:36:47 +00:00
|
|
|
return Response(
|
2024-03-01 00:01:00 +00:00
|
|
|
books.jsonifyBook(book),
|
2024-02-02 18:36:47 +00:00
|
|
|
status=status.HTTP_201_CREATED,
|
|
|
|
)
|