Coverage for cookbook/integration/recettetek.py: 17%
100 statements
« prev ^ index » next coverage.py v7.4.0, created at 2023-12-29 00:47 +0100
« prev ^ index » next coverage.py v7.4.0, created at 2023-12-29 00:47 +0100
1import imghdr
2import json
3import re
4from io import BytesIO
5from zipfile import ZipFile
7import requests
8import validators
10from django.utils.translation import gettext as _
11from cookbook.helper.image_processing import get_filetype
12from cookbook.helper.ingredient_parser import IngredientParser
13from cookbook.integration.integration import Integration
14from cookbook.models import Ingredient, Keyword, Recipe, Step
17class RecetteTek(Integration):
19 def import_file_name_filter(self, zip_info_object):
20 print("testing", zip_info_object.filename)
21 return re.match(r'^recipes_0.json$', zip_info_object.filename) or re.match(r'^recipes.json$', zip_info_object.filename)
23 def split_recipe_file(self, file):
25 recipe_json = json.loads(file)
27 recipe_list = [r for r in recipe_json]
29 return recipe_list
31 def get_recipe_from_file(self, file):
33 # Create initial recipe with just a title and a description
34 recipe = Recipe.objects.create(name=file['title'], created_by=self.request.user, internal=True, space=self.request.space, )
36 # set the description as an empty string for later use for the source URL, in case there is no description text.
37 recipe.description = ''
39 try:
40 if file['description'] != '':
41 recipe.description = file['description'].strip()
42 except Exception as e:
43 print(recipe.name, ': failed to parse recipe description ', str(e))
45 instructions = file['instructions']
46 if not instructions:
47 instructions = ''
49 step = Step.objects.create(instruction=instructions, space=self.request.space, show_ingredients_table=self.request.user.userpreference.show_step_ingredients,)
51 # Append the original import url to the step (if it exists)
52 try:
53 if file['url'] != '':
54 step.instruction += '\n\n' + _('Imported from') + ': ' + file['url']
55 step.save()
56 except Exception as e:
57 print(recipe.name, ': failed to import source url ', str(e))
59 try:
60 # Process the ingredients. Assumes 1 ingredient per line.
61 ingredient_parser = IngredientParser(self.request, True)
62 for ingredient in file['ingredients'].split('\n'):
63 if len(ingredient.strip()) > 0:
64 amount, unit, food, note = ingredient_parser.parse(ingredient.strip())
65 f = ingredient_parser.get_food(ingredient)
66 u = ingredient_parser.get_unit(unit)
67 step.ingredients.add(Ingredient.objects.create(
68 food=f, unit=u, amount=amount, note=note, original_text=ingredient, space=self.request.space,
69 ))
70 except Exception as e:
71 print(recipe.name, ': failed to parse recipe ingredients ', str(e))
72 recipe.steps.add(step)
74 # Attempt to import prep/cooking times
75 # quick hack, this assumes only one number in the quantity field.
76 try:
77 if file['quantity'] != '':
78 for item in file['quantity'].split(' '):
79 if item.isdigit():
80 recipe.servings = int(item)
81 break
82 except Exception as e:
83 print(recipe.name, ': failed to parse quantity ', str(e))
85 try:
86 if file['totalTime'] != '':
87 recipe.waiting_time = int(file['totalTime'])
88 except Exception as e:
89 print(recipe.name, ': failed to parse total times ', str(e))
91 try:
92 if file['preparationTime'] != '':
93 recipe.working_time = int(file['preparationTime'])
94 except Exception as e:
95 print(recipe.name, ': failed to parse prep time ', str(e))
97 try:
98 if file['cookingTime'] != '':
99 recipe.waiting_time = int(file['cookingTime'])
100 except Exception as e:
101 print(recipe.name, ': failed to parse cooking time ', str(e))
103 recipe.save()
105 # Import the recipe keywords
106 try:
107 if file['keywords'] != '':
108 for keyword in file['keywords'].split(';'):
109 k, created = Keyword.objects.get_or_create(name=keyword.strip(), space=self.request.space)
110 recipe.keywords.add(k)
111 recipe.save()
112 except Exception as e:
113 print(recipe.name, ': failed to parse keywords ', str(e))
115 # TODO: Parse Nutritional Information
117 # Import the original image from the zip file, if we cannot do that, attempt to download it again.
118 try:
119 if file['pictures'][0] != '':
120 image_file_name = file['pictures'][0].split('/')[-1]
121 for f in self.files:
122 if '.rtk' in f['name']:
123 import_zip = ZipFile(f['file'])
124 self.import_recipe_image(recipe, BytesIO(import_zip.read(image_file_name)), filetype=get_filetype(image_file_name))
125 else:
126 if file['originalPicture'] != '':
127 url = file['originalPicture']
128 if validators.url(url, public=True):
129 response = requests.get(url)
130 if imghdr.what(BytesIO(response.content)) is not None:
131 self.import_recipe_image(recipe, BytesIO(response.content), filetype=get_filetype(file['originalPicture']))
132 else:
133 raise Exception("Original image failed to download.")
134 except Exception as e:
135 print(recipe.name, ': failed to import image ', str(e))
137 return recipe
139 def get_file_from_recipe(self, recipe):
140 raise NotImplementedError('Method not implemented in storage integration')