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

1import imghdr 

2import json 

3import re 

4from io import BytesIO 

5from zipfile import ZipFile 

6 

7import requests 

8import validators 

9 

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 

15 

16 

17class RecetteTek(Integration): 

18 

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) 

22 

23 def split_recipe_file(self, file): 

24 

25 recipe_json = json.loads(file) 

26 

27 recipe_list = [r for r in recipe_json] 

28 

29 return recipe_list 

30 

31 def get_recipe_from_file(self, file): 

32 

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, ) 

35 

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 = '' 

38 

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)) 

44 

45 instructions = file['instructions'] 

46 if not instructions: 

47 instructions = '' 

48 

49 step = Step.objects.create(instruction=instructions, space=self.request.space, show_ingredients_table=self.request.user.userpreference.show_step_ingredients,) 

50 

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)) 

58 

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) 

73 

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)) 

84 

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)) 

90 

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)) 

96 

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)) 

102 

103 recipe.save() 

104 

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)) 

114 

115 # TODO: Parse Nutritional Information 

116 

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)) 

136 

137 return recipe 

138 

139 def get_file_from_recipe(self, recipe): 

140 raise NotImplementedError('Method not implemented in storage integration')