diff --git a/ingredients/__init__.py b/ingredients/__init__.py index e318c1b..5c85cb2 100644 --- a/ingredients/__init__.py +++ b/ingredients/__init__.py @@ -1,48 +1,68 @@ from ingredients.db import Ingredient, find_ingredients_by_meal_id, find_ingredients_by_recipe_id, insert_ingredient, delete_ingredients_by_meal_id import units -from products import Product, find_product_by_tag +from products import Product, find_product_by_tag, get_or_create, add_missing_tags -from ingredient_parser import parse_multiple_ingredients +from ingredient_parser import parse_ingredient + +import re from typing import List -def parse_ingredient_from_nlp(ingredients: List[str]) -> Ingredient: - results = [] - for ingredient in parse_multiple_ingredients(ingredients): - name = ingredient.name.text if ingredient.name else '' - - quantity, unit = None, None - for amount in ingredient.amount: - if quantity is None and amount.quantity: - quantity = amount.quantity - - if unit is None and amount.unit: - real_unit = units.get_unit(amount.unit) - if real_unit: - unit = real_unit.name - - if isinstance(quantity, str): - try: - quantity = float(quantity) - except ValueError: - pass - - if quantity is None or not isinstance(quantity, (int, float)): - quantity = 1 - - if unit is None: - unit = units.ITEMS.name - - results.append(Ingredient(id=0, - line=ingredient.sentence, - name=name, - quantity=quantity, - unit=unit, - preparation=ingredient.preparation.text if ingredient.preparation else '', - product_id=-1 - )) +async def parse_ingredient_from_link(conn, link: str) -> Ingredient: + match = re.match(r'^(\d+)?\s*(http.*)$', link) + if not match: + return None - return results + quantity = int(match.group(1)) if match.group(1) else 1 + url = match.group(2) + product = await get_or_create(conn, url, []) + if product: + await add_missing_tags(conn, product, [product.name]) + + return Ingredient(id=-1, + name=product.name, + line=f"{quantity}x {product.name}", + unit=units.ITEMS.name, + quantity=quantity, + preparation='', + product_id=product.id, + product=product + ) + +def parse_ingredient_from_nlp(ingredient_string: str) -> Ingredient: + ingredient = parse_ingredient(ingredient_string) + name = ingredient.name.text if ingredient.name else '' + + quantity, unit = None, None + for amount in ingredient.amount: + if quantity is None and amount.quantity: + quantity = amount.quantity + + if unit is None and amount.unit: + real_unit = units.get_unit(amount.unit) + if real_unit: + unit = real_unit.name + + if isinstance(quantity, str): + try: + quantity = float(quantity) + except ValueError: + pass + + if quantity is None or not isinstance(quantity, (int, float)): + quantity = 1 + + if unit is None: + unit = units.ITEMS.name + + return Ingredient(id=0, + line=ingredient.sentence, + name=name, + quantity=quantity, + unit=unit, + preparation=ingredient.preparation.text if ingredient.preparation else '', + product_id=-1 + ) async def _find_existing_product(conn, ingredient: str) -> Product: async for item in find_product_by_tag(conn, ingredient): diff --git a/main.py b/main.py index eb7ef3c..f40dda3 100644 --- a/main.py +++ b/main.py @@ -44,7 +44,24 @@ async def parse_ingredients(lines: Annotated[ Query(alias="ingredients", title="Array of ingredients to parse")], conn: sqlite3.Connection = Depends(get_db)) -> List[ingredients.Ingredient]: - result = ingredients.parse_ingredient_from_nlp(lines) + + had_links = False + result = [] + for line in lines: + ingredient = await ingredients.parse_ingredient_from_link(conn, line) + if ingredient: + result.append(ingredient) + had_links = True + continue + + ingredient = ingredients.parse_ingredient_from_nlp(line) + if ingredient: + result.append(ingredient) + continue + + if had_links: + await conn.commit() + await ingredients.match_existing_products(conn, result) return result diff --git a/products/__init__.py b/products/__init__.py index 86da4bb..5313c28 100644 --- a/products/__init__.py +++ b/products/__init__.py @@ -26,7 +26,7 @@ async def create_product(link: str) -> Product: _dump_json_data_to_log(data, product_id) quantity, unit = get_package_size(data) - product = Product( + product = Product( id=0, product_id=product_id, name=data['Product']['Name'], diff --git a/recipes/__init__.py b/recipes/__init__.py index f7ea5d6..8f51bf8 100644 --- a/recipes/__init__.py +++ b/recipes/__init__.py @@ -2,7 +2,7 @@ from persons import Person from recipes.db import Recipe, insert_recipe, find_recipe_by_id, get_all, find_recipes_by_name, row_to_recipe, load_recipe_ingredients, hide_recipe from recipes.scraping import scrape_recipe_ldata as _scrape_recipe_ldata -from ingredients import parse_ingredient_from_nlp as _parse_ingredient_from_nlp, match_existing_products as _match_existing_products +from ingredients import parse_ingredient_from_nlp, match_existing_products import re @@ -32,8 +32,8 @@ def find_yield(recipe_ldata: dict) -> int: return 4 async def _get_recipe_from_ldata(conn, url: str, ldata: dict, created_by: Person) -> dict: - ingredients = _parse_ingredient_from_nlp(ldata['recipeIngredient']) - ingredients = await _match_existing_products(conn, ingredients) + ingredients = parse_ingredient_from_nlp(ldata['recipeIngredient']) + ingredients = await match_existing_products(conn, ingredients) name = ldata['name'] if 'name' in ldata else url images = ldata['image'] if 'image' in ldata else [] serves = find_yield(ldata)