diff --git a/cookbook/forms.py b/cookbook/forms.py
index f6296c35..d905d768 100644
--- a/cookbook/forms.py
+++ b/cookbook/forms.py
@@ -129,13 +129,14 @@ class ImportExportBase(forms.Form):
MEALMASTER = 'MEALMASTER'
REZKONV = 'REZKONV'
OPENEATS = 'OPENEATS'
+ PLANTOEAT = 'PLANTOEAT'
type = forms.ChoiceField(choices=(
(DEFAULT, _('Default')), (PAPRIKA, 'Paprika'), (NEXTCLOUD, 'Nextcloud Cookbook'),
(MEALIE, 'Mealie'), (CHOWDOWN, 'Chowdown'), (SAFRON, 'Safron'), (CHEFTAP, 'ChefTap'),
(PEPPERPLATE, 'Pepperplate'), (RECETTETEK, 'RecetteTek'), (RECIPESAGE, 'Recipe Sage'), (DOMESTICA, 'Domestica'),
(MEALMASTER, 'MealMaster'), (REZKONV, 'RezKonv'), (OPENEATS, 'Openeats'), (RECIPEKEEPER, 'Recipe Keeper'),
-
+ (PLANTOEAT, 'Plantoeat'),
))
diff --git a/cookbook/integration/plantoeat.py b/cookbook/integration/plantoeat.py
new file mode 100644
index 00000000..32e871f9
--- /dev/null
+++ b/cookbook/integration/plantoeat.py
@@ -0,0 +1,93 @@
+from io import BytesIO
+
+import requests
+
+from cookbook.helper.ingredient_parser import parse, get_food, get_unit
+from cookbook.integration.integration import Integration
+from cookbook.models import Recipe, Step, Ingredient, Keyword
+
+
+class Plantoeat(Integration):
+
+ def get_recipe_from_file(self, file):
+ ingredient_mode = False
+ direction_mode = False
+
+ image_url = None
+ tags = None
+ ingredients = []
+ directions = []
+ description = ''
+ for line in file.replace('\r', '').split('\n'):
+ if line.strip() != '':
+ if 'Title:' in line:
+ title = line.replace('Title:', '').replace('"', '').strip()
+ if 'Description:' in line:
+ description = line.replace('Description:', '').strip()
+ if 'Source:' in line or 'Serves:' in line or 'Prep Time:' in line or 'Cook Time:' in line:
+ directions.append(line.strip() + '\n')
+ if 'Photo Url:' in line:
+ image_url = line.replace('Photo Url:', '').strip()
+ if 'Tags:' in line:
+ tags = line.replace('Tags:', '').strip()
+ if ingredient_mode:
+ if len(line) > 2 and 'Instructions:' not in line:
+ ingredients.append(line.strip())
+ if direction_mode:
+ if len(line) > 2:
+ directions.append(line.strip() + '\n')
+ if 'Ingredients:' in line:
+ ingredient_mode = True
+ if 'Directions:' in line:
+ ingredient_mode = False
+ direction_mode = True
+
+ recipe = Recipe.objects.create(name=title, description=description, created_by=self.request.user, internal=True, space=self.request.space)
+
+ step = Step.objects.create(
+ instruction='\n'.join(directions) + '\n\n', space=self.request.space,
+ )
+
+ if tags:
+ for k in tags.split(','):
+ keyword, created = Keyword.objects.get_or_create(name=k.strip(), space=self.request.space)
+ recipe.keywords.add(keyword)
+
+ for ingredient in ingredients:
+ if len(ingredient.strip()) > 0:
+ amount, unit, ingredient, note = parse(ingredient)
+ 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, space=self.request.space,
+ ))
+ recipe.steps.add(step)
+
+ if image_url:
+ try:
+ response = requests.get(image_url)
+ self.import_recipe_image(recipe, BytesIO(response.content))
+ except Exception as e:
+ print('failed to import image ', str(e))
+
+ return recipe
+
+ def split_recipe_file(self, file):
+ recipe_list = []
+ current_recipe = ''
+
+ for fl in file.readlines():
+ line = fl.decode("ANSI")
+ if line.startswith('--------------'):
+ if current_recipe != '':
+ recipe_list.append(current_recipe)
+ current_recipe = ''
+ else:
+ current_recipe = ''
+ else:
+ current_recipe += line + '\n'
+
+ if current_recipe != '':
+ recipe_list.append(current_recipe)
+
+ return recipe_list
diff --git a/cookbook/models.py b/cookbook/models.py
index e46a1153..886a0e82 100644
--- a/cookbook/models.py
+++ b/cookbook/models.py
@@ -41,7 +41,6 @@ class TreeManager(MP_NodeManager):
def get_or_create(self, **kwargs):
kwargs['name'] = kwargs['name'].strip()
try:
- print(f'checking name {kwargs["name"]}')
return self.get(name__exact=kwargs['name'], space=kwargs['space']), False
except self.model.DoesNotExist:
with scopes_disabled():
diff --git a/cookbook/templates/url_import.html b/cookbook/templates/url_import.html
index 9da96d3c..da180f34 100644
--- a/cookbook/templates/url_import.html
+++ b/cookbook/templates/url_import.html
@@ -84,6 +84,7 @@
+
diff --git a/cookbook/views/import_export.py b/cookbook/views/import_export.py
index 48e131c4..26135d54 100644
--- a/cookbook/views/import_export.py
+++ b/cookbook/views/import_export.py
@@ -20,6 +20,7 @@ from cookbook.integration.mealmaster import MealMaster
from cookbook.integration.nextcloud_cookbook import NextcloudCookbook
from cookbook.integration.openeats import OpenEats
from cookbook.integration.paprika import Paprika
+from cookbook.integration.plantoeat import Plantoeat
from cookbook.integration.recipekeeper import RecipeKeeper
from cookbook.integration.recettetek import RecetteTek
from cookbook.integration.recipesage import RecipeSage
@@ -59,6 +60,8 @@ def get_integration(request, export_type):
return MealMaster(request, export_type)
if export_type == ImportExportBase.OPENEATS:
return OpenEats(request, export_type)
+ if export_type == ImportExportBase.PLANTOEAT:
+ return Plantoeat(request, export_type)
@group_required('user')
diff --git a/docs/features/import_export.md b/docs/features/import_export.md
index 90612af2..576f964a 100644
--- a/docs/features/import_export.md
+++ b/docs/features/import_export.md
@@ -35,7 +35,7 @@ Overview of the capabilities of the different integrations.
| MealMaster | ✔️ | ❌ | ❌ |
| RezKonv | ✔️ | ❌ | ❌ |
| OpenEats | ✔️ | ❌ | ⌚ |
-| OpenEats | ✔️ | ❌ | ✔ |
+| Plantoeat | ✔️ | ❌ | ✔ |
✔ = implemented, ❌ = not implemented and not possible/planned, ⌚ = not yet implemented