1
0
Fork 0
mirror of https://github.com/mealie-recipes/mealie.git synced 2025-08-05 05:25:26 +02:00

feat: Import + Translate recipe images with OpenAI (#3974)

Co-authored-by: Johan Lindell <johan@lindell.me>
Co-authored-by: boc-the-git <3479092+boc-the-git@users.noreply.github.com>
This commit is contained in:
Michael Genson 2024-08-17 17:07:01 -05:00 committed by GitHub
parent 3d921cb677
commit 8a15f400e1
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
23 changed files with 924 additions and 241 deletions

View file

@ -0,0 +1,58 @@
import json
import pytest
from fastapi.testclient import TestClient
from mealie.schema.openai.recipe import (
OpenAIRecipe,
OpenAIRecipeIngredient,
OpenAIRecipeInstruction,
OpenAIRecipeNotes,
)
from mealie.services.openai import OpenAIService
from tests.utils import api_routes
from tests.utils.factories import random_int, random_string
from tests.utils.fixture_schemas import TestUser
def test_openai_create_recipe_from_image(
api_client: TestClient,
monkeypatch: pytest.MonkeyPatch,
unique_user: TestUser,
test_image_jpg: str,
):
async def mock_get_response(self, prompt: str, message: str, *args, **kwargs) -> str | None:
data = OpenAIRecipe(
name=random_string(),
description=random_string(),
recipe_yield=random_string(),
total_time=random_string(),
prep_time=random_string(),
perform_time=random_string(),
ingredients=[OpenAIRecipeIngredient(text=random_string()) for _ in range(random_int(5, 10))],
instructions=[OpenAIRecipeInstruction(text=random_string()) for _ in range(1, random_int(5, 10))],
notes=[OpenAIRecipeNotes(text=random_string()) for _ in range(random_int(2, 5))],
)
return data.model_dump_json()
monkeypatch.setattr(OpenAIService, "get_response", mock_get_response)
with open(test_image_jpg, "rb") as f:
r = api_client.post(
api_routes.recipes_create_from_image,
files={"images": ("test_image_jpg.jpg", f, "image/jpeg")},
data={"extension": "jpg"},
headers=unique_user.token,
)
assert r.status_code == 201
# since OpenAI is mocked, we don't need to validate the data, we just need to make sure a recipe is created,
# and that it has an image
slug: str = json.loads(r.text)
r = api_client.get(api_routes.recipes_slug(slug), headers=unique_user.token)
assert r.status_code == 200
recipe_id = r.json()["id"]
r = api_client.get(
api_routes.media_recipes_recipe_id_images_file_name(recipe_id, "original.webp"), headers=unique_user.token
)
assert r.status_code == 200

View file

@ -17,20 +17,14 @@ admin_email = "/api/admin/email"
"""`/api/admin/email`"""
admin_groups = "/api/admin/groups"
"""`/api/admin/groups`"""
admin_logs = "/api/admin/logs"
"""`/api/admin/logs`"""
admin_maintenance = "/api/admin/maintenance"
"""`/api/admin/maintenance`"""
admin_maintenance_clean_images = "/api/admin/maintenance/clean/images"
"""`/api/admin/maintenance/clean/images`"""
admin_maintenance_clean_logs = "/api/admin/maintenance/clean/logs"
"""`/api/admin/maintenance/clean/logs`"""
admin_maintenance_clean_recipe_folders = "/api/admin/maintenance/clean/recipe-folders"
"""`/api/admin/maintenance/clean/recipe-folders`"""
admin_maintenance_clean_temp = "/api/admin/maintenance/clean/temp"
"""`/api/admin/maintenance/clean/temp`"""
admin_maintenance_logs = "/api/admin/maintenance/logs"
"""`/api/admin/maintenance/logs`"""
admin_maintenance_storage = "/api/admin/maintenance/storage"
"""`/api/admin/maintenance/storage`"""
admin_users = "/api/admin/users"
@ -47,6 +41,8 @@ app_about_startup_info = "/api/app/about/startup-info"
"""`/api/app/about/startup-info`"""
app_about_theme = "/api/app/about/theme"
"""`/api/app/about/theme`"""
auth_logout = "/api/auth/logout"
"""`/api/auth/logout`"""
auth_refresh = "/api/auth/refresh"
"""`/api/auth/refresh`"""
auth_token = "/api/auth/token"
@ -143,6 +139,8 @@ recipes_bulk_actions_settings = "/api/recipes/bulk-actions/settings"
"""`/api/recipes/bulk-actions/settings`"""
recipes_bulk_actions_tag = "/api/recipes/bulk-actions/tag"
"""`/api/recipes/bulk-actions/tag`"""
recipes_create_from_image = "/api/recipes/create-from-image"
"""`/api/recipes/create-from-image`"""
recipes_create_from_zip = "/api/recipes/create-from-zip"
"""`/api/recipes/create-from-zip`"""
recipes_create_url = "/api/recipes/create-url"
@ -212,11 +210,6 @@ def admin_groups_item_id(item_id):
return f"{prefix}/admin/groups/{item_id}"
def admin_logs_num(num):
"""`/api/admin/logs/{num}`"""
return f"{prefix}/admin/logs/{num}"
def admin_users_item_id(item_id):
"""`/api/admin/users/{item_id}`"""
return f"{prefix}/admin/users/{item_id}"
@ -362,6 +355,11 @@ def groups_webhooks_item_id(item_id):
return f"{prefix}/groups/webhooks/{item_id}"
def groups_webhooks_item_id_test(item_id):
"""`/api/groups/webhooks/{item_id}/test`"""
return f"{prefix}/groups/webhooks/{item_id}/test"
def media_recipes_recipe_id_assets_file_name(recipe_id, file_name):
"""`/api/media/recipes/{recipe_id}/assets/{file_name}`"""
return f"{prefix}/media/recipes/{recipe_id}/assets/{file_name}"