diff --git a/mealie/db/data_initialization/init_units_foods.py b/mealie/db/data_initialization/init_units_foods.py index 71df21b8c4bb..e284a819204e 100644 --- a/mealie/db/data_initialization/init_units_foods.py +++ b/mealie/db/data_initialization/init_units_foods.py @@ -1,4 +1,4 @@ -from mealie.schema.recipe.units_and_foods import CreateIngredientUnit +from mealie.schema.recipe import CreateIngredientUnit from sqlalchemy.orm.session import Session from ..data_access_layer import DatabaseAccessLayer diff --git a/mealie/routes/recipe/comments.py b/mealie/routes/recipe/comments.py index 5bb910e0e9bf..a6f47a442341 100644 --- a/mealie/routes/recipe/comments.py +++ b/mealie/routes/recipe/comments.py @@ -5,7 +5,7 @@ from mealie.db.database import db from mealie.db.db_setup import generate_session from mealie.routes.deps import get_current_user from mealie.routes.routers import UserAPIRouter -from mealie.schema.recipe import CommentIn, CommentOut, CommentSaveToDB +from mealie.schema.recipe import CommentOut, CreateComment, SaveComment from mealie.schema.user import UserInDB from sqlalchemy.orm.session import Session @@ -15,20 +15,20 @@ router = UserAPIRouter() @router.post("/{slug}/comments") async def create_comment( slug: str, - new_comment: CommentIn, + new_comment: CreateComment, session: Session = Depends(generate_session), current_user: UserInDB = Depends(get_current_user), ): """ Create comment in the Database """ - new_comment = CommentSaveToDB(user=current_user.id, text=new_comment.text, recipe_slug=slug) + new_comment = SaveComment(user=current_user.id, text=new_comment.text, recipe_slug=slug) return db.comments.create(session, new_comment) @router.put("/{slug}/comments/{id}") async def update_comment( id: int, - new_comment: CommentIn, + new_comment: CreateComment, session: Session = Depends(generate_session), current_user: UserInDB = Depends(get_current_user), ): diff --git a/mealie/routes/recipe/image_and_assets.py b/mealie/routes/recipe/image_and_assets.py index 5856d7f769a8..20785f2954e5 100644 --- a/mealie/routes/recipe/image_and_assets.py +++ b/mealie/routes/recipe/image_and_assets.py @@ -5,7 +5,7 @@ from fastapi.datastructures import UploadFile from mealie.db.database import db from mealie.db.db_setup import generate_session from mealie.routes.routers import UserAPIRouter -from mealie.schema.recipe import Recipe, RecipeAsset, RecipeURLIn +from mealie.schema.recipe import CreateRecipeByURL, Recipe, RecipeAsset from mealie.services.image.image import scrape_image, write_image from slugify import slugify from sqlalchemy.orm.session import Session @@ -16,7 +16,7 @@ user_router = UserAPIRouter() @user_router.post("/{recipe_slug}/image") def scrape_image_url( recipe_slug: str, - url: RecipeURLIn, + url: CreateRecipeByURL, ): """ Removes an existing image and replaces it with the incoming file. """ diff --git a/mealie/routes/recipe/recipe_crud_routes.py b/mealie/routes/recipe/recipe_crud_routes.py index 3cabe31663ed..3c834cc8ff98 100644 --- a/mealie/routes/recipe/recipe_crud_routes.py +++ b/mealie/routes/recipe/recipe_crud_routes.py @@ -10,7 +10,7 @@ from mealie.db.database import db from mealie.db.db_setup import generate_session from mealie.routes.deps import get_current_user, is_logged_in, temporary_zip_path from mealie.routes.routers import UserAPIRouter -from mealie.schema.recipe import Recipe, RecipeImageTypes, RecipeURLIn +from mealie.schema.recipe import CreateRecipeByURL, Recipe, RecipeImageTypes from mealie.schema.recipe.recipe import CreateRecipe from mealie.schema.user import UserInDB from mealie.services.events import create_recipe_event @@ -51,14 +51,14 @@ def create_from_name( @user_router.post("/test-scrape-url") -def test_parse_recipe_url(url: RecipeURLIn): +def test_parse_recipe_url(url: CreateRecipeByURL): return scrape_url(url.url) @user_router.post("/create-url", status_code=201, response_model=str) def parse_recipe_url( background_tasks: BackgroundTasks, - url: RecipeURLIn, + url: CreateRecipeByURL, session: Session = Depends(generate_session), current_user: UserInDB = Depends(get_current_user), ): diff --git a/mealie/routes/unit_and_foods/food_routes.py b/mealie/routes/unit_and_foods/food_routes.py index 4cf3bf969fb4..3331683b2a42 100644 --- a/mealie/routes/unit_and_foods/food_routes.py +++ b/mealie/routes/unit_and_foods/food_routes.py @@ -2,7 +2,7 @@ from fastapi import Depends, status from mealie.db.database import db from mealie.db.db_setup import Session, generate_session from mealie.routes.routers import UserAPIRouter -from mealie.schema.recipe.units_and_foods import CreateIngredientFood, IngredientFood +from mealie.schema.recipe import CreateIngredientFood, IngredientFood router = UserAPIRouter() diff --git a/mealie/routes/unit_and_foods/unit_routes.py b/mealie/routes/unit_and_foods/unit_routes.py index e560436cd237..69026a5235c1 100644 --- a/mealie/routes/unit_and_foods/unit_routes.py +++ b/mealie/routes/unit_and_foods/unit_routes.py @@ -2,7 +2,7 @@ from fastapi import Depends, status from mealie.db.database import db from mealie.db.db_setup import Session, generate_session from mealie.routes.routers import UserAPIRouter -from mealie.schema.recipe.units_and_foods import CreateIngredientUnit, IngredientUnit +from mealie.schema.recipe import CreateIngredientUnit, IngredientUnit router = UserAPIRouter() diff --git a/mealie/schema/admin/settings.py b/mealie/schema/admin/settings.py index bbade5b31c28..4002db51bb8f 100644 --- a/mealie/schema/admin/settings.py +++ b/mealie/schema/admin/settings.py @@ -4,7 +4,7 @@ from fastapi_camelcase import CamelModel from pydantic import validator from slugify import slugify -from ..recipe.category import CategoryBase, RecipeCategoryResponse +from ..recipe.recipe_category import CategoryBase, RecipeCategoryResponse class SiteSettings(CamelModel): diff --git a/mealie/schema/recipe/__init__.py b/mealie/schema/recipe/__init__.py index 35d69062b42f..e98e6f97d682 100644 --- a/mealie/schema/recipe/__init__.py +++ b/mealie/schema/recipe/__init__.py @@ -1,4 +1,6 @@ -from .category import * -from .comments import * -from .helpers import * from .recipe import * +from .recipe_category import * +from .recipe_comments import * +from .recipe_image_types import * +from .recipe_ingredient import * +from .request_helpers import * diff --git a/mealie/schema/recipe/recipe.py b/mealie/schema/recipe/recipe.py index 3a55d774f0a2..ce1a3bb1cc19 100644 --- a/mealie/schema/recipe/recipe.py +++ b/mealie/schema/recipe/recipe.py @@ -1,91 +1,34 @@ import datetime -from enum import Enum from pathlib import Path from typing import Any, Optional from fastapi_camelcase import CamelModel -from mealie.core.config import app_dirs, settings +from mealie.core.config import app_dirs from mealie.db.models.recipe.recipe import RecipeModel from pydantic import BaseModel, Field, validator from pydantic.utils import GetterDict from slugify import slugify -from .comments import CommentOut -from .units_and_foods import IngredientFood, IngredientUnit +from .recipe_asset import RecipeAsset +from .recipe_comments import CommentOut +from .recipe_ingredient import RecipeIngredient +from .recipe_notes import RecipeNote +from .recipe_nutrition import Nutrition +from .recipe_settings import RecipeSettings +from .recipe_step import RecipeStep + + +class CreateRecipeByURL(BaseModel): + url: str + + class Config: + schema_extra = {"example": {"url": "https://myfavoriterecipes.com/recipes"}} class CreateRecipe(CamelModel): name: str -class RecipeImageTypes(str, Enum): - original = "original.webp" - min = "min-original.webp" - tiny = "tiny-original.webp" - - -class RecipeSettings(CamelModel): - public: bool = settings.RECIPE_PUBLIC - show_nutrition: bool = settings.RECIPE_SHOW_NUTRITION - show_assets: bool = settings.RECIPE_SHOW_ASSETS - landscape_view: bool = settings.RECIPE_LANDSCAPE_VIEW - disable_comments: bool = settings.RECIPE_DISABLE_COMMENTS - disable_amount: bool = settings.RECIPE_DISABLE_AMOUNT - - class Config: - orm_mode = True - - -class RecipeNote(BaseModel): - title: str - text: str - - class Config: - orm_mode = True - - -class RecipeStep(CamelModel): - title: Optional[str] = "" - text: str - - class Config: - orm_mode = True - - -class RecipeAsset(CamelModel): - name: str - icon: str - file_name: Optional[str] - - class Config: - orm_mode = True - - -class Nutrition(CamelModel): - calories: Optional[str] - fat_content: Optional[str] - protein_content: Optional[str] - carbohydrate_content: Optional[str] - fiber_content: Optional[str] - sodium_content: Optional[str] - sugar_content: Optional[str] - - class Config: - orm_mode = True - - -class RecipeIngredient(CamelModel): - title: Optional[str] - note: Optional[str] - unit: Optional[IngredientUnit] - food: Optional[IngredientFood] - disable_amount: bool = True - quantity: int = 1 - - class Config: - orm_mode = True - - class RecipeSummary(CamelModel): id: Optional[int] name: Optional[str] @@ -196,15 +139,10 @@ class Recipe(RecipeSummary): @validator("slug", always=True, pre=True) def validate_slug(slug: str, values): - if not values["name"]: + if not values.get("name"): return slug - name: str = values["name"] - calc_slug: str = slugify(name) - if slug != calc_slug: - slug = calc_slug - - return slug + return slugify(values["name"]) @validator("recipe_ingredient", always=True, pre=True) def validate_ingredients(recipe_ingredient, values): @@ -215,28 +153,3 @@ class Recipe(RecipeSummary): return [RecipeIngredient(note=x) for x in recipe_ingredient] return recipe_ingredient - - -class AllRecipeRequest(BaseModel): - properties: list[str] - limit: Optional[int] - - class Config: - schema_extra = { - "example": { - "properties": ["name", "slug", "image"], - "limit": 100, - } - } - - -class RecipeURLIn(BaseModel): - url: str - - class Config: - schema_extra = {"example": {"url": "https://myfavoriterecipes.com/recipes"}} - - -class SlugResponse(BaseModel): - class Config: - schema_extra = {"example": "adult-mac-and-cheese"} diff --git a/mealie/schema/recipe/recipe_asset.py b/mealie/schema/recipe/recipe_asset.py new file mode 100644 index 000000000000..5cf4d2e1f574 --- /dev/null +++ b/mealie/schema/recipe/recipe_asset.py @@ -0,0 +1,12 @@ +from typing import Optional + +from fastapi_camelcase import CamelModel + + +class RecipeAsset(CamelModel): + name: str + icon: str + file_name: Optional[str] + + class Config: + orm_mode = True diff --git a/mealie/schema/recipe/category.py b/mealie/schema/recipe/recipe_category.py similarity index 100% rename from mealie/schema/recipe/category.py rename to mealie/schema/recipe/recipe_category.py diff --git a/mealie/schema/recipe/recipe_comments.py b/mealie/schema/recipe/recipe_comments.py new file mode 100644 index 000000000000..3ade1a3b9b0b --- /dev/null +++ b/mealie/schema/recipe/recipe_comments.py @@ -0,0 +1,44 @@ +from datetime import datetime +from typing import Optional + +from fastapi_camelcase import CamelModel +from pydantic.utils import GetterDict + + +class UserBase(CamelModel): + id: int + username: Optional[str] + admin: bool + + class Config: + orm_mode = True + + +class CreateComment(CamelModel): + text: str + + +class SaveComment(CreateComment): + recipe_slug: str + user: int + + class Config: + orm_mode = True + + +class CommentOut(CreateComment): + id: int + uuid: str + recipe_slug: str + date_added: datetime + user: UserBase + + class Config: + orm_mode = True + + @classmethod + def getter_dict(_cls, name_orm): + return { + **GetterDict(name_orm), + "recipe_slug": name_orm.recipe.slug, + } diff --git a/mealie/schema/recipe/recipe_image_types.py b/mealie/schema/recipe/recipe_image_types.py new file mode 100644 index 000000000000..3906ce7ad4d8 --- /dev/null +++ b/mealie/schema/recipe/recipe_image_types.py @@ -0,0 +1,7 @@ +from enum import Enum + + +class RecipeImageTypes(str, Enum): + original = "original.webp" + min = "min-original.webp" + tiny = "tiny-original.webp" diff --git a/mealie/schema/recipe/recipe_ingredient.py b/mealie/schema/recipe/recipe_ingredient.py new file mode 100644 index 000000000000..e822e6e1c104 --- /dev/null +++ b/mealie/schema/recipe/recipe_ingredient.py @@ -0,0 +1,39 @@ +from typing import Optional, Union + +from fastapi_camelcase import CamelModel + + +class CreateIngredientFood(CamelModel): + name: str + description: str = "" + + +class CreateIngredientUnit(CreateIngredientFood): + fraction: bool = True + abbreviation: str = "" + + +class IngredientFood(CreateIngredientFood): + id: int + + class Config: + orm_mode = True + + +class IngredientUnit(CreateIngredientUnit): + id: int + + class Config: + orm_mode = True + + +class RecipeIngredient(CamelModel): + title: Optional[str] + note: Optional[str] + unit: Optional[Union[CreateIngredientUnit, IngredientUnit]] + food: Optional[Union[CreateIngredientFood, IngredientFood]] + disable_amount: bool = True + quantity: float = 1 + + class Config: + orm_mode = True diff --git a/mealie/schema/recipe/recipe_notes.py b/mealie/schema/recipe/recipe_notes.py new file mode 100644 index 000000000000..ae8633a884b9 --- /dev/null +++ b/mealie/schema/recipe/recipe_notes.py @@ -0,0 +1,9 @@ +from pydantic import BaseModel + + +class RecipeNote(BaseModel): + title: str + text: str + + class Config: + orm_mode = True diff --git a/mealie/schema/recipe/recipe_nutrition.py b/mealie/schema/recipe/recipe_nutrition.py new file mode 100644 index 000000000000..8b6d0aee3e35 --- /dev/null +++ b/mealie/schema/recipe/recipe_nutrition.py @@ -0,0 +1,16 @@ +from typing import Optional + +from fastapi_camelcase import CamelModel + + +class Nutrition(CamelModel): + calories: Optional[str] + fat_content: Optional[str] + protein_content: Optional[str] + carbohydrate_content: Optional[str] + fiber_content: Optional[str] + sodium_content: Optional[str] + sugar_content: Optional[str] + + class Config: + orm_mode = True diff --git a/mealie/schema/recipe/recipe_settings.py b/mealie/schema/recipe/recipe_settings.py new file mode 100644 index 000000000000..5f0cdfe2e2c4 --- /dev/null +++ b/mealie/schema/recipe/recipe_settings.py @@ -0,0 +1,14 @@ +from fastapi_camelcase import CamelModel +from mealie.core.config import settings + + +class RecipeSettings(CamelModel): + public: bool = settings.RECIPE_PUBLIC + show_nutrition: bool = settings.RECIPE_SHOW_NUTRITION + show_assets: bool = settings.RECIPE_SHOW_ASSETS + landscape_view: bool = settings.RECIPE_LANDSCAPE_VIEW + disable_comments: bool = settings.RECIPE_DISABLE_COMMENTS + disable_amount: bool = settings.RECIPE_DISABLE_AMOUNT + + class Config: + orm_mode = True diff --git a/mealie/schema/recipe/recipe_step.py b/mealie/schema/recipe/recipe_step.py new file mode 100644 index 000000000000..ddcf676e5540 --- /dev/null +++ b/mealie/schema/recipe/recipe_step.py @@ -0,0 +1,11 @@ +from typing import Optional + +from fastapi_camelcase import CamelModel + + +class RecipeStep(CamelModel): + title: Optional[str] = "" + text: str + + class Config: + orm_mode = True diff --git a/mealie/schema/recipe/request_helpers.py b/mealie/schema/recipe/request_helpers.py new file mode 100644 index 000000000000..2c7cf2562a37 --- /dev/null +++ b/mealie/schema/recipe/request_helpers.py @@ -0,0 +1,13 @@ +from fastapi_camelcase import CamelModel +from pydantic import BaseModel + +# TODO: Should these exist?!?!?!?!? + + +class RecipeSlug(CamelModel): + slug: str + + +class SlugResponse(BaseModel): + class Config: + schema_extra = {"example": "adult-mac-and-cheese"} diff --git a/mealie/schema/recipe_old/__init__.py b/mealie/schema/recipe_old/__init__.py new file mode 100644 index 000000000000..35d69062b42f --- /dev/null +++ b/mealie/schema/recipe_old/__init__.py @@ -0,0 +1,4 @@ +from .category import * +from .comments import * +from .helpers import * +from .recipe import * diff --git a/mealie/schema/recipe_old/category.py b/mealie/schema/recipe_old/category.py new file mode 100644 index 000000000000..ac2287ed2a86 --- /dev/null +++ b/mealie/schema/recipe_old/category.py @@ -0,0 +1,48 @@ +from typing import List, Optional + +from fastapi_camelcase import CamelModel +from pydantic.utils import GetterDict + + +class CategoryIn(CamelModel): + name: str + + +class CategoryBase(CategoryIn): + id: int + slug: str + + class Config: + orm_mode = True + + @classmethod + def getter_dict(_cls, name_orm): + return { + **GetterDict(name_orm), + "total_recipes": len(name_orm.recipes), + } + + +class RecipeCategoryResponse(CategoryBase): + recipes: Optional[List["Recipe"]] + + class Config: + schema_extra = {"example": {"id": 1, "name": "dinner", "recipes": [{}]}} + + +class TagIn(CategoryIn): + pass + + +class TagBase(CategoryBase): + pass + + +class RecipeTagResponse(RecipeCategoryResponse): + pass + + +from .recipe import Recipe + +RecipeCategoryResponse.update_forward_refs() +RecipeTagResponse.update_forward_refs() diff --git a/mealie/schema/recipe/comments.py b/mealie/schema/recipe_old/comments.py similarity index 100% rename from mealie/schema/recipe/comments.py rename to mealie/schema/recipe_old/comments.py diff --git a/mealie/schema/recipe/helpers.py b/mealie/schema/recipe_old/helpers.py similarity index 100% rename from mealie/schema/recipe/helpers.py rename to mealie/schema/recipe_old/helpers.py diff --git a/mealie/schema/recipe_old/recipe.py b/mealie/schema/recipe_old/recipe.py new file mode 100644 index 000000000000..3a55d774f0a2 --- /dev/null +++ b/mealie/schema/recipe_old/recipe.py @@ -0,0 +1,242 @@ +import datetime +from enum import Enum +from pathlib import Path +from typing import Any, Optional + +from fastapi_camelcase import CamelModel +from mealie.core.config import app_dirs, settings +from mealie.db.models.recipe.recipe import RecipeModel +from pydantic import BaseModel, Field, validator +from pydantic.utils import GetterDict +from slugify import slugify + +from .comments import CommentOut +from .units_and_foods import IngredientFood, IngredientUnit + + +class CreateRecipe(CamelModel): + name: str + + +class RecipeImageTypes(str, Enum): + original = "original.webp" + min = "min-original.webp" + tiny = "tiny-original.webp" + + +class RecipeSettings(CamelModel): + public: bool = settings.RECIPE_PUBLIC + show_nutrition: bool = settings.RECIPE_SHOW_NUTRITION + show_assets: bool = settings.RECIPE_SHOW_ASSETS + landscape_view: bool = settings.RECIPE_LANDSCAPE_VIEW + disable_comments: bool = settings.RECIPE_DISABLE_COMMENTS + disable_amount: bool = settings.RECIPE_DISABLE_AMOUNT + + class Config: + orm_mode = True + + +class RecipeNote(BaseModel): + title: str + text: str + + class Config: + orm_mode = True + + +class RecipeStep(CamelModel): + title: Optional[str] = "" + text: str + + class Config: + orm_mode = True + + +class RecipeAsset(CamelModel): + name: str + icon: str + file_name: Optional[str] + + class Config: + orm_mode = True + + +class Nutrition(CamelModel): + calories: Optional[str] + fat_content: Optional[str] + protein_content: Optional[str] + carbohydrate_content: Optional[str] + fiber_content: Optional[str] + sodium_content: Optional[str] + sugar_content: Optional[str] + + class Config: + orm_mode = True + + +class RecipeIngredient(CamelModel): + title: Optional[str] + note: Optional[str] + unit: Optional[IngredientUnit] + food: Optional[IngredientFood] + disable_amount: bool = True + quantity: int = 1 + + class Config: + orm_mode = True + + +class RecipeSummary(CamelModel): + id: Optional[int] + name: Optional[str] + slug: str = "" + image: Optional[Any] + + description: Optional[str] + recipe_category: Optional[list[str]] = [] + tags: Optional[list[str]] = [] + rating: Optional[int] + + date_added: Optional[datetime.date] + date_updated: Optional[datetime.datetime] + + class Config: + orm_mode = True + + @classmethod + def getter_dict(_cls, name_orm: RecipeModel): + return { + **GetterDict(name_orm), + "recipe_category": [x.name for x in name_orm.recipe_category], + "tags": [x.name for x in name_orm.tags], + } + + +class Recipe(RecipeSummary): + recipe_yield: Optional[str] + recipe_ingredient: Optional[list[RecipeIngredient]] = [] + recipe_instructions: Optional[list[RecipeStep]] = [] + nutrition: Optional[Nutrition] + tools: Optional[list[str]] = [] + + total_time: Optional[str] = None + prep_time: Optional[str] = None + perform_time: Optional[str] = None + + # Mealie Specific + settings: Optional[RecipeSettings] = RecipeSettings() + assets: Optional[list[RecipeAsset]] = [] + notes: Optional[list[RecipeNote]] = [] + org_url: Optional[str] = Field(None, alias="orgURL") + extras: Optional[dict] = {} + + comments: Optional[list[CommentOut]] = [] + + @staticmethod + def directory_from_slug(slug) -> Path: + return app_dirs.RECIPE_DATA_DIR.joinpath(slug) + + @property + def directory(self) -> Path: + dir = app_dirs.RECIPE_DATA_DIR.joinpath(self.slug) + dir.mkdir(exist_ok=True, parents=True) + return dir + + @property + def asset_dir(self) -> Path: + dir = self.directory.joinpath("assets") + dir.mkdir(exist_ok=True, parents=True) + return dir + + @property + def image_dir(self) -> Path: + dir = self.directory.joinpath("images") + dir.mkdir(exist_ok=True, parents=True) + return dir + + class Config: + orm_mode = True + + @classmethod + def getter_dict(_cls, name_orm: RecipeModel): + return { + **GetterDict(name_orm), + # "recipe_ingredient": [x.note for x in name_orm.recipe_ingredient], + "recipe_category": [x.name for x in name_orm.recipe_category], + "tags": [x.name for x in name_orm.tags], + "tools": [x.tool for x in name_orm.tools], + "extras": {x.key_name: x.value for x in name_orm.extras}, + } + + schema_extra = { + "example": { + "name": "Chicken and Rice With Leeks and Salsa Verde", + "description": "This one-skillet dinner gets deep oniony flavor from lots of leeks cooked down to jammy tenderness.", + "image": "chicken-and-rice-with-leeks-and-salsa-verde.jpg", + "recipe_yield": "4 Servings", + "recipe_ingredient": [ + "1 1/2 lb. skinless, boneless chicken thighs (4-8 depending on size)", + "Kosher salt, freshly ground pepper", + "3 Tbsp. unsalted butter, divided", + ], + "recipe_instructions": [ + { + "text": "Season chicken with salt and pepper.", + }, + ], + "slug": "chicken-and-rice-with-leeks-and-salsa-verde", + "tags": ["favorite", "yummy!"], + "recipe_category": ["Dinner", "Pasta"], + "notes": [{"title": "Watch Out!", "text": "Prep the day before!"}], + "org_url": "https://www.bonappetit.com/recipe/chicken-and-rice-with-leeks-and-salsa-verde", + "rating": 3, + "extras": {"message": "Don't forget to defrost the chicken!"}, + } + } + + @validator("slug", always=True, pre=True) + def validate_slug(slug: str, values): + if not values["name"]: + return slug + name: str = values["name"] + calc_slug: str = slugify(name) + + if slug != calc_slug: + slug = calc_slug + + return slug + + @validator("recipe_ingredient", always=True, pre=True) + def validate_ingredients(recipe_ingredient, values): + if not recipe_ingredient or not isinstance(recipe_ingredient, list): + return recipe_ingredient + + if all(isinstance(elem, str) for elem in recipe_ingredient): + return [RecipeIngredient(note=x) for x in recipe_ingredient] + + return recipe_ingredient + + +class AllRecipeRequest(BaseModel): + properties: list[str] + limit: Optional[int] + + class Config: + schema_extra = { + "example": { + "properties": ["name", "slug", "image"], + "limit": 100, + } + } + + +class RecipeURLIn(BaseModel): + url: str + + class Config: + schema_extra = {"example": {"url": "https://myfavoriterecipes.com/recipes"}} + + +class SlugResponse(BaseModel): + class Config: + schema_extra = {"example": "adult-mac-and-cheese"} diff --git a/mealie/schema/recipe/units_and_foods.py b/mealie/schema/recipe_old/units_and_foods.py similarity index 100% rename from mealie/schema/recipe/units_and_foods.py rename to mealie/schema/recipe_old/units_and_foods.py