Coverage for cookbook/integration/mealie.py: 19%
70 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 json
2import re
3from io import BytesIO
4from zipfile import ZipFile
6from cookbook.helper.image_processing import get_filetype
7from cookbook.helper.ingredient_parser import IngredientParser
8from cookbook.helper.recipe_url_import import parse_servings, parse_servings_text, parse_time
9from cookbook.integration.integration import Integration
10from cookbook.models import Ingredient, Keyword, Recipe, Step
13class Mealie(Integration):
15 def import_file_name_filter(self, zip_info_object):
16 return re.match(r'^recipes/([A-Za-z\d\s\-_()\[\]\u00C0-\u017F])+/([A-Za-z\d\s\-_()\[\]\u00C0-\u017F])+.json$', zip_info_object.filename)
18 def get_recipe_from_file(self, file):
19 recipe_json = json.loads(file.getvalue().decode("utf-8"))
21 description = '' if len(recipe_json['description'].strip()) > 500 else recipe_json['description'].strip()
23 recipe = Recipe.objects.create(
24 name=recipe_json['name'].strip(), description=description,
25 created_by=self.request.user, internal=True, space=self.request.space)
27 for s in recipe_json['recipe_instructions']:
28 step = Step.objects.create(instruction=s['text'], space=self.request.space, show_ingredients_table=self.request.user.userpreference.show_step_ingredients, )
29 recipe.steps.add(step)
31 step = recipe.steps.first()
32 if not step: # if there is no step in the exported data
33 step = Step.objects.create(instruction='', space=self.request.space, )
34 recipe.steps.add(step)
36 if len(recipe_json['description'].strip()) > 500:
37 step.instruction = recipe_json['description'].strip() + '\n\n' + step.instruction
39 ingredient_parser = IngredientParser(self.request, True)
40 for ingredient in recipe_json['recipe_ingredient']:
41 try:
42 if ingredient['food']:
43 f = ingredient_parser.get_food(ingredient['food'])
44 u = ingredient_parser.get_unit(ingredient['unit'])
45 amount = ingredient['quantity']
46 note = ingredient['note']
47 original_text = None
48 else:
49 amount, unit, food, note = ingredient_parser.parse(ingredient['note'])
50 f = ingredient_parser.get_food(food)
51 u = ingredient_parser.get_unit(unit)
52 original_text = ingredient['note']
53 step.ingredients.add(Ingredient.objects.create(
54 food=f, unit=u, amount=amount, note=note, original_text=original_text, space=self.request.space,
55 ))
56 except Exception:
57 pass
59 if 'tags' in recipe_json and len(recipe_json['tags']) > 0:
60 for k in recipe_json['tags']:
61 if 'name' in k:
62 keyword, created = Keyword.objects.get_or_create(name=k['name'].strip(), space=self.request.space)
63 recipe.keywords.add(keyword)
65 if 'notes' in recipe_json and len(recipe_json['notes']) > 0:
66 notes_text = "#### Notes \n\n"
67 for n in recipe_json['notes']:
68 notes_text += f'{n["text"]} \n'
70 step = Step.objects.create(
71 instruction=notes_text, space=self.request.space,
72 )
73 recipe.steps.add(step)
75 if 'recipe_yield' in recipe_json:
76 recipe.servings = parse_servings(recipe_json['recipe_yield'])
77 recipe.servings_text = parse_servings_text(recipe_json['recipe_yield'])
79 if 'total_time' in recipe_json and recipe_json['total_time'] is not None:
80 recipe.working_time = parse_time(recipe_json['total_time'])
82 if 'org_url' in recipe_json:
83 recipe.source_url = recipe_json['org_url']
85 recipe.save()
87 for f in self.files:
88 if '.zip' in f['name']:
89 import_zip = ZipFile(f['file'])
90 try:
91 self.import_recipe_image(recipe, BytesIO(import_zip.read(f'recipes/{recipe_json["slug"]}/images/min-original.webp')),
92 filetype=get_filetype(f'recipes/{recipe_json["slug"]}/images/original'))
93 except Exception:
94 pass
96 return recipe
98 def get_file_from_recipe(self, recipe):
99 raise NotImplementedError('Method not implemented in storage integration')