improvements to recipekeeper importer

This commit is contained in:
vabene1111 2021-06-09 17:23:14 +02:00
parent 46db6d4186
commit f7d85bb4b8
5 changed files with 45 additions and 28 deletions

View File

@ -358,3 +358,11 @@ def normalize_string(string):
unescaped_string = re.sub(r'\n\s*\n', '\n\n', unescaped_string)
unescaped_string = unescaped_string.replace("\xa0", " ").replace("\t", " ").strip()
return unescaped_string
def iso_duration_to_minutes(string):
match = re.match(
r'P((?P<years>\d+)Y)?((?P<months>\d+)M)?((?P<weeks>\d+)W)?((?P<days>\d+)D)?T((?P<hours>\d+)H)?((?P<minutes>\d+)M)?((?P<seconds>\d+)S)?',
string
).groupdict()
return int(match['days'] or 0) * 24 * 60 + int(match['hours'] or 0) * 60 + int(match['minutes'] or 0)

View File

@ -1,5 +1,6 @@
import datetime
import json
import re
import uuid
from io import BytesIO, StringIO
from zipfile import ZipFile, BadZipFile
@ -216,3 +217,4 @@ class Integration:
- data - string content for file to get created in export zip
"""
raise NotImplementedError('Method not implemented in integration')

View File

@ -6,6 +6,7 @@ from zipfile import ZipFile
from django.utils.translation import gettext as _
from cookbook.helper.ingredient_parser import parse, get_food, get_unit
from cookbook.helper.recipe_url_import import parse_servings, iso_duration_to_minutes
from cookbook.integration.integration import Integration
from cookbook.models import Recipe, Step, Food, Unit, Ingredient, Keyword
@ -32,39 +33,37 @@ class RecipeKeeper(Integration):
keyword, created = Keyword.objects.get_or_create(name=category.get("content"), space=self.request.space)
recipe.keywords.add(keyword)
# TODO: import prep and cook times
# Recipe Keeper uses ISO 8601 format for its duration periods.
try:
recipe.servings = parse_servings(file.find("span", {"itemprop": "recipeYield"}).text.strip())
recipe.working_time = iso_duration_to_minutes(file.find("span", {"meta": "prepTime"}).text.strip())
recipe.waiting_time = iso_duration_to_minutes(file.find("span", {"meta": "cookTime"}).text.strip())
recipe.save()
except AttributeError:
pass
step = Step.objects.create(instruction='')
for ingredient in file.find("div", {"itemprop": "recipeIngredients"}).findChildren("p"):
if ingredient.text == "":
continue
amount, unit, ingredient, note = parse(ingredient.text.strip())
f = get_food(ingredient, self.request.space)
u = get_unit(unit, self.request.space)
step.ingredients.add(Ingredient.objects.create(
food=f, unit=u, amount=amount, note=note
))
source_url_added = False
ingredients_added = False
for s in file.find("div", {"itemprop": "recipeDirections"}).find_all("p"):
if s.text == "":
continue
step.instruction += s.text + ' \n'
step = Step.objects.create(
instruction=s.text
)
if file.find("span", {"itemprop": "recipeSource"}).text != '':
step.instruction += "\n\nImported from: " + file.find("span", {"itemprop": "recipeSource"}).text
step.save()
source_url_added = True
if not source_url_added:
# If there is a source URL, add it to the first step field.
if file.find("span", {"itemprop": "recipeSource"}).text != '':
step.instruction += "\n\nImported from: " + file.find("span", {"itemprop": "recipeSource"}).text
step.save()
source_url_added = True
if not ingredients_added:
ingredients_added = True
for ingredient in file.find("div", {"itemprop": "recipeIngredients"}).findChildren("p"):
if ingredient.text == "":
continue
amount, unit, ingredient, note = parse(ingredient.text.strip())
f = get_food(ingredient, self.request.space)
u = get_unit(unit, self.request.space)
step.ingredients.add(Ingredient.objects.create(
food=f, unit=u, amount=amount, note=note
))
recipe.steps.add(step)
recipe.steps.add(step)
# import the Primary recipe image that is stored in the Zip
try:

View File

@ -100,6 +100,9 @@
<label class="btn btn-outline-info btn-sm" @click="recipe_app='RECIPESAGE'">
<input type="radio" autocomplete="off"> Recipesage
</label>
<label class="btn btn-outline-info btn-sm" @click="recipe_app='RECIPEKEEPER'">
<input type="radio" autocomplete="off"> Recipekeeper
</label>
<label class="btn btn-outline-info btn-sm" @click="recipe_app='DOMESTICA'">
<input type="radio" autocomplete="off"> Domestica
</label>

View File

@ -35,6 +35,7 @@ Overview of the capabilities of the different integrations.
| MealMaster | ✔️ | ❌ | ❌ |
| RezKonv | ✔️ | ❌ | ❌ |
| OpenEats | ✔️ | ❌ | ⌚ |
| OpenEats | ✔️ | ❌ | ✔ |
✔ = implemented, ❌ = not implemented and not possible/planned, ⌚ = not yet implemented
@ -161,7 +162,11 @@ The RezKonv format is primarily used in the german recipe manager RezKonv Suite.
To migrate from RezKonv Suite to Tandoor select `Export > Gesamtes Kochbuch exportieren` (the last option in the export menu).
The generated file can simply be imported into Tandoor.
As i only had limited sample data feel free to open an issue if your RezKonv export cannot be imported.
As I only had limited sample data feel free to open an issue if your RezKonv export cannot be imported.
## Recipekeeper
Recipe keeper allows to export a zip file containing recipes and images using its apps.
This zip file can simply be imported into Tandoor.
## OpenEats
OpenEats does not provide any way to export the data using the interface. Luckily it is relatively easy to export it from the command line.