Coverage for cookbook/integration/recipesage.py: 21%

61 statements  

« prev     ^ index     » next       coverage.py v7.4.0, created at 2023-12-29 00:47 +0100

1import json 

2from io import BytesIO 

3 

4import requests 

5import validators 

6 

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, Recipe, Step 

11 

12 

13class RecipeSage(Integration): 

14 

15 def get_recipe_from_file(self, file): 

16 

17 recipe = Recipe.objects.create( 

18 name=file['name'].strip(), 

19 created_by=self.request.user, internal=True, 

20 space=self.request.space) 

21 

22 if file['recipeYield'] != '': 

23 recipe.servings = parse_servings(file['recipeYield']) 

24 recipe.servings_text = parse_servings_text(file['recipeYield']) 

25 

26 try: 

27 if 'totalTime' in file and file['totalTime'] != '': 

28 recipe.working_time = parse_time(file['totalTime']) 

29 

30 if 'timePrep' in file and file['prepTime'] != '': 

31 recipe.working_time = parse_time(file['timePrep']) 

32 recipe.waiting_time = parse_time(file['totalTime']) - parse_time(file['timePrep']) 

33 except Exception as e: 

34 print('failed to parse time ', str(e)) 

35 

36 recipe.save() 

37 

38 ingredient_parser = IngredientParser(self.request, True) 

39 ingredients_added = False 

40 for s in file['recipeInstructions']: 

41 step = Step.objects.create( 

42 instruction=s['text'], space=self.request.space, show_ingredients_table=self.request.user.userpreference.show_step_ingredients, 

43 ) 

44 if not ingredients_added: 

45 ingredients_added = True 

46 

47 for ingredient in file['recipeIngredient']: 

48 amount, unit, food, note = ingredient_parser.parse(ingredient) 

49 f = ingredient_parser.get_food(food) 

50 u = ingredient_parser.get_unit(unit) 

51 step.ingredients.add(Ingredient.objects.create( 

52 food=f, unit=u, amount=amount, note=note, original_text=ingredient, space=self.request.space, 

53 )) 

54 recipe.steps.add(step) 

55 

56 if len(file['image']) > 0: 

57 try: 

58 url = file['image'][0] 

59 if validators.url(url, public=True): 

60 response = requests.get(url) 

61 self.import_recipe_image(recipe, BytesIO(response.content)) 

62 except Exception as e: 

63 print('failed to import image ', str(e)) 

64 

65 return recipe 

66 

67 def get_file_from_recipe(self, recipe): 

68 data = { 

69 '@context': 'http://schema.org', 

70 '@type': 'Recipe', 

71 'creditText': '', 

72 'isBasedOn': '', 

73 'name': recipe.name, 

74 'description': recipe.description, 

75 'prepTime': str(recipe.working_time), 

76 'totalTime': str(recipe.waiting_time + recipe.working_time), 

77 'recipeYield': str(recipe.servings), 

78 'image': [], 

79 'recipeCategory': [], 

80 'comment': [], 

81 'recipeIngredient': [], 

82 'recipeInstructions': [], 

83 } 

84 

85 for s in recipe.steps.all(): 

86 data['recipeInstructions'].append({ 

87 '@type': 'HowToStep', 

88 'text': s.instruction 

89 }) 

90 

91 for i in s.ingredients.all(): 

92 data['recipeIngredient'].append(f'{float(i.amount)} {i.unit} {i.food}') 

93 

94 return data 

95 

96 def get_files_from_recipes(self, recipes, el, cookie): 

97 json_list = [] 

98 for r in recipes: 

99 json_list.append(self.get_file_from_recipe(r)) 

100 

101 el.exported_recipes += 1 

102 el.msg += self.get_recipe_processed_msg(r) 

103 el.save() 

104 

105 return [[self.get_export_file_name('json'), json.dumps(json_list)]] 

106 

107 def split_recipe_file(self, file): 

108 return json.loads(file.read().decode("utf-8"))