Merge pull request #591 from itsmegb/importer-reciepekeeper

New Importer - Reciepe Keeper
This commit is contained in:
vabene1111 2021-06-09 16:42:49 +02:00 committed by GitHub
commit 46db6d4186
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 99 additions and 2 deletions

View File

@ -121,6 +121,7 @@ class ImportExportBase(forms.Form):
SAFRON = 'SAFRON'
CHEFTAP = 'CHEFTAP'
PEPPERPLATE = 'PEPPERPLATE'
RECIPEKEEPER = 'RECIPEKEEPER'
RECETTETEK = 'RECETTETEK'
RECIPESAGE = 'RECIPESAGE'
DOMESTICA = 'DOMESTICA'
@ -132,7 +133,8 @@ class ImportExportBase(forms.Form):
(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'),
(MEALMASTER, 'MealMaster'), (REZKONV, 'RezKonv'), (OPENEATS, 'Openeats'), (RECIPEKEEPER, 'Recipe Keeper'),
))

View File

@ -104,7 +104,18 @@ class Integration:
try:
self.files = files
for f in files:
if '.zip' in f['name'] or '.paprikarecipes' in f['name']:
if 'RecipeKeeper' in f['name']:
import_zip = ZipFile(f['file'])
for z in import_zip.filelist:
if self.import_file_name_filter(z):
data_list = self.split_recipe_file(import_zip.read(z.filename).decode('utf-8'))
for d in data_list:
recipe = self.get_recipe_from_file(d)
recipe.keywords.add(self.keyword)
il.msg += f'{recipe.pk} - {recipe.name} \n'
self.handle_duplicates(recipe, import_duplicates)
import_zip.close()
elif '.zip' in f['name'] or '.paprikarecipes' in f['name']:
import_zip = ZipFile(f['file'])
for z in import_zip.filelist:
if self.import_file_name_filter(z):

View File

@ -0,0 +1,81 @@
import re
from bs4 import BeautifulSoup
from io import BytesIO
from zipfile import ZipFile
from django.utils.translation import gettext as _
from cookbook.helper.ingredient_parser import parse, get_food, get_unit
from cookbook.integration.integration import Integration
from cookbook.models import Recipe, Step, Food, Unit, Ingredient, Keyword
class RecipeKeeper(Integration):
def import_file_name_filter(self, zip_info_object):
return re.match(r'^recipes.html$', zip_info_object.filename)
def split_recipe_file(self, file):
recipe_html = BeautifulSoup(file, 'html.parser')
return recipe_html.find_all('div', class_='recipe-details')
def get_recipe_from_file(self, file):
# 'file' comes is as a beautifulsoup object
recipe = Recipe.objects.create(name=file.find("h2", {"itemprop": "name"}).text.strip(), created_by=self.request.user, internal=True, space=self.request.space, )
# add 'Courses' and 'Categories' as keywords
for course in file.find_all("span", {"itemprop": "recipeCourse"}):
keyword, created = Keyword.objects.get_or_create(name=course.text, space=self.request.space)
recipe.keywords.add(keyword)
for category in file.find_all("meta", {"itemprop": "recipeCategory"}):
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.
source_url_added = False
ingredients_added = False
for s in file.find("div", {"itemprop": "recipeDirections"}).find_all("p"):
if s.text == "":
continue
step = Step.objects.create(
instruction=s.text
)
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)
# import the Primary recipe image that is stored in the Zip
try:
for f in self.files:
if '.zip' in f['name']:
import_zip = ZipFile(f['file'])
self.import_recipe_image(recipe, BytesIO(import_zip.read(file.find("img", class_="recipe-photo").get("src"))))
except Exception as e:
pass
return recipe
def get_file_from_recipe(self, recipe):
raise NotImplementedError('Method not implemented in storage integration')

View File

@ -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.recipekeeper import RecipeKeeper
from cookbook.integration.recettetek import RecetteTek
from cookbook.integration.recipesage import RecipeSage
from cookbook.integration.rezkonv import RezKonv
@ -46,6 +47,8 @@ def get_integration(request, export_type):
return Pepperplate(request, export_type)
if export_type == ImportExportBase.DOMESTICA:
return Domestica(request, export_type)
if export_type == ImportExportBase.RECIPEKEEPER:
return RecipeKeeper(request, export_type)
if export_type == ImportExportBase.RECETTETEK:
return RecetteTek(request, export_type)
if export_type == ImportExportBase.RECIPESAGE: