From 7f41f9ab0faa495d2e569789070c9b74471e63fb Mon Sep 17 00:00:00 2001 From: Kurbanov Bulat Date: Sun, 21 Nov 2021 23:05:54 +0300 Subject: [PATCH] Add caption, add cache update on get --- src/app/services/cache_updater.py | 48 ++++++++++++++++++++---------- src/app/services/caption_getter.py | 33 ++++++++++++++++++++ src/app/services/library_client.py | 18 +++++++++-- src/app/views.py | 3 ++ 4 files changed, 84 insertions(+), 18 deletions(-) create mode 100644 src/app/services/caption_getter.py diff --git a/src/app/services/cache_updater.py b/src/app/services/cache_updater.py index fb2f9e9..8db1818 100644 --- a/src/app/services/cache_updater.py +++ b/src/app/services/cache_updater.py @@ -1,8 +1,11 @@ +from typing import Optional + import asyncio -from app.services.library_client import get_books, Book +from app.services.library_client import get_books, get_book, Book from app.services.downloader import download from app.services.files_uploader import upload_file +from app.services.caption_getter import get_caption from app.models import CachedFile @@ -38,6 +41,25 @@ class CacheUpdater: self.all_books_checked = True + @classmethod + async def _cache_file(cls, book: Book, file_type) -> Optional[CachedFile]: + data = await download(book.source.id, book.remote_id, file_type) + + if data is None: + return None + + content, filename = data + + caption = get_caption(book) + + upload_data = await upload_file(content, filename, caption) + + return await CachedFile.objects.create( + object_id=book.id, + object_type=file_type, + data=upload_data.data + ) + async def _start_worker(self): while not self.all_books_checked or not self.queue.empty(): try: @@ -48,20 +70,7 @@ class CacheUpdater: await asyncio.sleep(0.1) continue - data = await download(book.source.id, book.remote_id, file_type) - - if data is None: - return - - content, filename = data - - upload_data = await upload_file(content, filename, 'Test') - - await CachedFile.objects.create( - object_id=book.id, - object_type=file_type, - data=upload_data.data - ) + await self._cache_file(book, file_type) async def _update(self): await asyncio.gather( @@ -74,3 +83,12 @@ class CacheUpdater: async def update(cls): updater = cls() return await updater._update() + + @classmethod + async def cache_file(cls, book_id: int, file_type: str) -> Optional[CachedFile]: + book = await get_book(book_id) + + if file_type not in book.available_types: + return None # ToDO: raise HTTPException + + return await cls._cache_file(book, file_type) diff --git a/src/app/services/caption_getter.py b/src/app/services/caption_getter.py new file mode 100644 index 0000000..03e3b58 --- /dev/null +++ b/src/app/services/caption_getter.py @@ -0,0 +1,33 @@ +from app.services.library_client import Book, BookAuthor + + +def get_author_string(author: BookAuthor) -> str: + author_parts = [] + + if author.last_name: + author_parts.append(author.last_name) + + if author.first_name: + author_parts.append(author.first_name) + + if author.middle_name: + author_parts.append(author.middle_name) + + return " ".join(author_parts) + + +def get_caption(book: Book) -> str: + caption_title = f"📖 {book.title}" + + caption_authors_parts = [] + for author in book.authors: + caption_authors_parts.append( + f"👤 {get_author_string(author)}" + ) + + if not caption_authors_parts: + return caption_title + + caption_authors = "\n".join(caption_authors_parts) + + return caption_title + "\n\n" + caption_authors diff --git a/src/app/services/library_client.py b/src/app/services/library_client.py index 2568cdc..f4973e9 100644 --- a/src/app/services/library_client.py +++ b/src/app/services/library_client.py @@ -40,11 +40,23 @@ class Book(BaseModel): authors: list[BookAuthor] -async def get_books(page: int, page_size: int) -> Page[Book]: - headers = {"Authorization": env_config.LIBRARY_API_KEY} +class BookDetail(Book): + is_deleted: bool + +AUTH_HEADERS = {"Authorization": env_config.LIBRARY_API_KEY} + + +async def get_book(book_id: int) -> BookDetail: async with httpx.AsyncClient() as client: - response = await client.get(f"{env_config.LIBRARY_URL}/api/v1/books/?page={page}&size={page_size}&is_deleted=false", headers=headers) + response = await client.get(f"{env_config.LIBRARY_URL}/api/v1/books/{book_id}", headers=AUTH_HEADERS) + + return BookDetail.parse_obj(response.json()) + + +async def get_books(page: int, page_size: int) -> Page[Book]: + async with httpx.AsyncClient() as client: + response = await client.get(f"{env_config.LIBRARY_URL}/api/v1/books/?page={page}&size={page_size}&is_deleted=false", headers=AUTH_HEADERS) data = response.json() diff --git a/src/app/views.py b/src/app/views.py index 58b5c9d..3963e71 100644 --- a/src/app/views.py +++ b/src/app/views.py @@ -20,6 +20,9 @@ async def get_cached_file(object_id: int, object_type: str): object_type=object_type ) + if not cached_file: + cached_file = await CacheUpdater.cache_file(object_id, object_type) + if not cached_file: raise HTTPException(status_code=status.HTTP_404_NOT_FOUND)