From 9dedc5b8fa675a14264fcad649a8a3760fe93666 Mon Sep 17 00:00:00 2001 From: Tiago Rascazzi Date: Sat, 29 Oct 2022 14:08:12 -0400 Subject: [PATCH] Added nextcloud export implementation --- cookbook/integration/nextcloud_cookbook.py | 92 +++++++++++++++++++++- vue/src/apps/ExportView/ExportView.vue | 1 + 2 files changed, 91 insertions(+), 2 deletions(-) diff --git a/cookbook/integration/nextcloud_cookbook.py b/cookbook/integration/nextcloud_cookbook.py index 6db53f70..baa8625c 100644 --- a/cookbook/integration/nextcloud_cookbook.py +++ b/cookbook/integration/nextcloud_cookbook.py @@ -1,7 +1,8 @@ import json import re -from io import BytesIO +from io import BytesIO, StringIO from zipfile import ZipFile +from PIL import Image from cookbook.helper.image_processing import get_filetype from cookbook.helper.ingredient_parser import IngredientParser @@ -96,5 +97,92 @@ class NextcloudCookbook(Integration): return recipe + def formatTime(self, min): + h = min//60 + m = min % 60 + return f'PT{h}H{m}M0S' + + def get_file_from_recipe(self, recipe): - raise NotImplementedError('Method not implemented in storage integration') + + export = {} + export['name'] = recipe.name + export['description'] = recipe.description + export['url'] = recipe.source_url + export['prepTime'] = self.formatTime(recipe.working_time) + export['cookTime'] = self.formatTime(recipe.waiting_time) + export['totalTime'] = self.formatTime(recipe.working_time+recipe.waiting_time) + export['recipeYield'] = recipe.servings + export['image'] = f'/Recipes/{recipe.name}/full.jpg' + export['imageUrl'] = f'/Recipes/{recipe.name}/full.jpg' + + recipeKeyword = [] + for k in recipe.keywords.all(): + recipeKeyword.append(k.name) + + export['keywords'] = recipeKeyword + + recipeInstructions = [] + recipeIngredient = [] + for s in recipe.steps.all(): + recipeInstructions.append(s.instruction) + + for i in s.ingredients.all(): + recipeIngredient.append(f'{float(i.amount)} {i.unit} {i.food}') + + export['recipeIngredient'] = recipeIngredient + export['recipeInstructions'] = recipeInstructions + + + return "recipe.json", json.dumps(export) + + def get_files_from_recipes(self, recipes, el, cookie): + export_zip_stream = BytesIO() + export_zip_obj = ZipFile(export_zip_stream, 'w') + + for recipe in recipes: + if recipe.internal and recipe.space == self.request.space: + + recipe_stream = StringIO() + filename, data = self.get_file_from_recipe(recipe) + recipe_stream.write(data) + export_zip_obj.writestr(f'{recipe.name}/{filename}', recipe_stream.getvalue()) + recipe_stream.close() + + try: + imageByte = recipe.image.file.read() + export_zip_obj.writestr(f'{recipe.name}/full.jpg', self.getJPEG(imageByte)) + export_zip_obj.writestr(f'{recipe.name}/thumb.jpg', self.getThumb(171, imageByte)) + export_zip_obj.writestr(f'{recipe.name}/thumb16.jpg', self.getThumb(16, imageByte)) + except ValueError: + pass + + el.exported_recipes += 1 + el.msg += self.get_recipe_processed_msg(recipe) + el.save() + + export_zip_obj.close() + + return [[ self.get_export_file_name(), export_zip_stream.getvalue() ]] + + def getJPEG(self, imageByte): + image = Image.open(BytesIO(imageByte)) + image = image.convert('RGB') + + bytes = BytesIO() + image.save(bytes, "JPEG") + return bytes.getvalue() + + def getThumb(self, size, imageByte): + image = Image.open(BytesIO(imageByte)) + + w, h = image.size + m = min(w, h) + + image = image.crop(((w-m)//2, (h-m)//2, (w+m)//2, (h+m)//2)) + image = image.resize([size, size], Image.Resampling.LANCZOS) + image = image.convert('RGB') + + bytes = BytesIO() + image.save(bytes, "JPEG") + return bytes.getvalue() diff --git a/vue/src/apps/ExportView/ExportView.vue b/vue/src/apps/ExportView/ExportView.vue index 5503eaa1..96a3dd1b 100644 --- a/vue/src/apps/ExportView/ExportView.vue +++ b/vue/src/apps/ExportView/ExportView.vue @@ -8,6 +8,7 @@