141 lines
5.7 KiB
Python
141 lines
5.7 KiB
Python
import imghdr
|
|
import json
|
|
import re
|
|
from io import BytesIO
|
|
from zipfile import ZipFile
|
|
|
|
import requests
|
|
import validators
|
|
|
|
from django.utils.translation import gettext as _
|
|
from cookbook.helper.image_processing import get_filetype
|
|
from cookbook.helper.ingredient_parser import IngredientParser
|
|
from cookbook.integration.integration import Integration
|
|
from cookbook.models import Ingredient, Keyword, Recipe, Step
|
|
|
|
|
|
class RecetteTek(Integration):
|
|
|
|
def import_file_name_filter(self, zip_info_object):
|
|
print("testing", zip_info_object.filename)
|
|
return re.match(r'^recipes_0.json$', zip_info_object.filename) or re.match(r'^recipes.json$', zip_info_object.filename)
|
|
|
|
def split_recipe_file(self, file):
|
|
|
|
recipe_json = json.loads(file)
|
|
|
|
recipe_list = [r for r in recipe_json]
|
|
|
|
return recipe_list
|
|
|
|
def get_recipe_from_file(self, file):
|
|
|
|
# Create initial recipe with just a title and a description
|
|
recipe = Recipe.objects.create(name=file['title'], created_by=self.request.user, internal=True, space=self.request.space, )
|
|
|
|
# set the description as an empty string for later use for the source URL, in case there is no description text.
|
|
recipe.description = ''
|
|
|
|
try:
|
|
if file['description'] != '':
|
|
recipe.description = file['description'].strip()
|
|
except Exception as e:
|
|
print(recipe.name, ': failed to parse recipe description ', str(e))
|
|
|
|
instructions = file['instructions']
|
|
if not instructions:
|
|
instructions = ''
|
|
|
|
step = Step.objects.create(instruction=instructions, space=self.request.space, show_ingredients_table=self.request.user.userpreference.show_step_ingredients,)
|
|
|
|
# Append the original import url to the step (if it exists)
|
|
try:
|
|
if file['url'] != '':
|
|
step.instruction += '\n\n' + _('Imported from') + ': ' + file['url']
|
|
step.save()
|
|
except Exception as e:
|
|
print(recipe.name, ': failed to import source url ', str(e))
|
|
|
|
try:
|
|
# Process the ingredients. Assumes 1 ingredient per line.
|
|
ingredient_parser = IngredientParser(self.request, True)
|
|
for ingredient in file['ingredients'].split('\n'):
|
|
if len(ingredient.strip()) > 0:
|
|
amount, unit, food, note = ingredient_parser.parse(ingredient.strip())
|
|
f = ingredient_parser.get_food(ingredient)
|
|
u = ingredient_parser.get_unit(unit)
|
|
step.ingredients.add(Ingredient.objects.create(
|
|
food=f, unit=u, amount=amount, note=note, original_text=ingredient, space=self.request.space,
|
|
))
|
|
except Exception as e:
|
|
print(recipe.name, ': failed to parse recipe ingredients ', str(e))
|
|
recipe.steps.add(step)
|
|
|
|
# Attempt to import prep/cooking times
|
|
# quick hack, this assumes only one number in the quantity field.
|
|
try:
|
|
if file['quantity'] != '':
|
|
for item in file['quantity'].split(' '):
|
|
if item.isdigit():
|
|
recipe.servings = int(item)
|
|
break
|
|
except Exception as e:
|
|
print(recipe.name, ': failed to parse quantity ', str(e))
|
|
|
|
try:
|
|
if file['totalTime'] != '':
|
|
recipe.waiting_time = int(file['totalTime'])
|
|
except Exception as e:
|
|
print(recipe.name, ': failed to parse total times ', str(e))
|
|
|
|
try:
|
|
if file['preparationTime'] != '':
|
|
recipe.working_time = int(file['preparationTime'])
|
|
except Exception as e:
|
|
print(recipe.name, ': failed to parse prep time ', str(e))
|
|
|
|
try:
|
|
if file['cookingTime'] != '':
|
|
recipe.waiting_time = int(file['cookingTime'])
|
|
except Exception as e:
|
|
print(recipe.name, ': failed to parse cooking time ', str(e))
|
|
|
|
recipe.save()
|
|
|
|
# Import the recipe keywords
|
|
try:
|
|
if file['keywords'] != '':
|
|
for keyword in file['keywords'].split(';'):
|
|
k, created = Keyword.objects.get_or_create(name=keyword.strip(), space=self.request.space)
|
|
recipe.keywords.add(k)
|
|
recipe.save()
|
|
except Exception as e:
|
|
print(recipe.name, ': failed to parse keywords ', str(e))
|
|
|
|
# TODO: Parse Nutritional Information
|
|
|
|
# Import the original image from the zip file, if we cannot do that, attempt to download it again.
|
|
try:
|
|
if file['pictures'][0] != '':
|
|
image_file_name = file['pictures'][0].split('/')[-1]
|
|
for f in self.files:
|
|
if '.rtk' in f['name']:
|
|
import_zip = ZipFile(f['file'])
|
|
self.import_recipe_image(recipe, BytesIO(import_zip.read(image_file_name)), filetype=get_filetype(image_file_name))
|
|
else:
|
|
if file['originalPicture'] != '':
|
|
url = file['originalPicture']
|
|
if validators.url(url, public=True):
|
|
response = requests.get(url)
|
|
if imghdr.what(BytesIO(response.content)) is not None:
|
|
self.import_recipe_image(recipe, BytesIO(response.content), filetype=get_filetype(file['originalPicture']))
|
|
else:
|
|
raise Exception("Original image failed to download.")
|
|
except Exception as e:
|
|
print(recipe.name, ': failed to import image ', str(e))
|
|
|
|
return recipe
|
|
|
|
def get_file_from_recipe(self, recipe):
|
|
raise NotImplementedError('Method not implemented in storage integration')
|