Modified files
storeapi/tasks.py
---
+++
@@ -1,8 +1,10 @@
import logging
+from json import JSONDecodeError
import httpx
-
+from databases import Database
from storeapi.config import config
+from storeapi.database import post_table
logger = logging.getLogger(__name__)
@@ -46,3 +48,68 @@
f" following link: {confirmation_url}"
),
)
+
+
+async def _generate_cute_creature_api(prompt: str):
+ logger.debug("Generating cute creature")
+ async with httpx.AsyncClient() as client:
+ try:
+ response = await client.post(
+ "https://api.deepai.org/api/cute-creature-generator",
+ data={"text": prompt},
+ headers={"api-key": config.DEEPAI_API_KEY},
+ timeout=60,
+ )
+ logger.debug(response)
+ response.raise_for_status()
+ return response.json()
+ except httpx.HTTPStatusError as err:
+ raise APIResponseError(
+ f"API request failed with status code {err.response.status_code}"
+ ) from err
+ except (JSONDecodeError, TypeError) as err:
+ raise APIResponseError("API response parsing failed") from err
+
+
+async def generate_and_add_to_post(
+ email: str,
+ post_id: int,
+ post_url: str,
+ database: Database,
+ prompt: str = "A blue british shorthair cat is sitting on a couch",
+):
+ try:
+ response = await _generate_cute_creature_api(prompt)
+ except APIResponseError:
+ return await send_simple_email(
+ email,
+ "Error generating image",
+ (
+ f"Hi {email}! Unfortunately there was an error generating an image"
+ "for your post."
+ ),
+ )
+
+ logger.debug("Connecting to database to update post")
+
+ query = (
+ post_table.update()
+ .where(post_table.c.id == post_id)
+ .values(image_url=response["output_url"])
+ )
+
+ logger.debug(query)
+
+ await database.execute(query)
+
+ logger.debug("Database connection in background task closed")
+
+ await send_simple_email(
+ email,
+ "Image generation completed",
+ (
+ f"Hi {email}! Your image has been generated and added to your post."
+ f" Please click on the following link to view it: {post_url}"
+ ),
+ )
+ return response
storeapi/tests/test_tasks.py
---
+++
@@ -1,7 +1,13 @@
import httpx
import pytest
-
-from storeapi.tasks import APIResponseError, send_simple_email
+from databases import Database
+from storeapi.database import database, post_table
+from storeapi.tasks import (
+ APIResponseError,
+ _generate_cute_creature_api,
+ generate_and_add_to_post,
+ send_simple_email,
+)
@pytest.mark.anyio
@@ -18,3 +24,60 @@
with pytest.raises(APIResponseError):
await send_simple_email("test@example.net", "Test Subject", "Test Body")
+
+
+@pytest.mark.anyio
+async def test_generate_cute_creature_api_success(mock_httpx_client):
+ json_data = {"output_url": "https://example.com/image.jpg"}
+
+ mock_httpx_client.post.return_value = httpx.Response(
+ status_code=200, json=json_data, request=httpx.Request("POST", "//")
+ )
+
+ result = await _generate_cute_creature_api("A cat")
+
+ assert result == json_data
+
+
+@pytest.mark.anyio
+async def test_generate_cute_creature_api_server_error(mock_httpx_client):
+ mock_httpx_client.post.return_value = httpx.Response(
+ status_code=500, content="", request=httpx.Request("POST", "//")
+ )
+
+ with pytest.raises(
+ APIResponseError, match="API request failed with status code 500"
+ ):
+ await _generate_cute_creature_api("A cat")
+
+
+@pytest.mark.anyio
+async def test_generate_cute_creature_api_json_error(mock_httpx_client):
+ mock_httpx_client.post.return_value = httpx.Response(
+ status_code=200, content="Not JSON", request=httpx.Request("POST", "//")
+ )
+
+ with pytest.raises(APIResponseError, match="API response parsing failed"):
+ await _generate_cute_creature_api("A cat")
+
+
+@pytest.mark.anyio
+async def test_generate_and_add_to_post_success(
+ mock_httpx_client, created_post: dict, confirmed_user: dict, db: Database
+):
+ json_data = {"output_url": "https://example.com/image.jpg"}
+
+ mock_httpx_client.post.return_value = httpx.Response(
+ status_code=200, json=json_data, request=httpx.Request("POST", "//")
+ )
+
+ await generate_and_add_to_post(
+ confirmed_user["email"], created_post["id"], "/post/1", db, "A cat"
+ )
+
+ # Check that after the background task runs, the post has been updated
+ query = post_table.select().where(post_table.c.id == created_post["id"])
+
+ updated_post = await database.fetch_one(query)
+
+ assert updated_post.image_url == json_data["output_url"]