import re import threading from io import BytesIO from django.core.cache import cache from django.contrib import messages from django.http import HttpResponse, HttpResponseRedirect, JsonResponse from django.shortcuts import render from django.urls import reverse from django.utils.translation import gettext as _ from cookbook.forms import ExportForm, ImportForm, ImportExportBase from cookbook.helper.permission_helper import group_required from cookbook.integration.cookbookapp import CookBookApp from cookbook.integration.copymethat import CopyMeThat from cookbook.integration.pepperplate import Pepperplate from cookbook.integration.cheftap import ChefTap from cookbook.integration.chowdown import Chowdown from cookbook.integration.default import Default from cookbook.integration.domestica import Domestica from cookbook.integration.mealie import Mealie from cookbook.integration.mealmaster import MealMaster from cookbook.integration.nextcloud_cookbook import NextcloudCookbook from cookbook.integration.openeats import OpenEats from cookbook.integration.paprika import Paprika from cookbook.integration.plantoeat import Plantoeat from cookbook.integration.recipekeeper import RecipeKeeper from cookbook.integration.recettetek import RecetteTek from cookbook.integration.recipesage import RecipeSage from cookbook.integration.rezkonv import RezKonv from cookbook.integration.saffron import Saffron from cookbook.integration.pdfexport import PDFexport from cookbook.models import Recipe, ImportLog, ExportLog, UserPreference from recipes import settings def get_integration(request, export_type): if export_type == ImportExportBase.DEFAULT: return Default(request, export_type) if export_type == ImportExportBase.PAPRIKA: return Paprika(request, export_type) if export_type == ImportExportBase.NEXTCLOUD: return NextcloudCookbook(request, export_type) if export_type == ImportExportBase.MEALIE: return Mealie(request, export_type) if export_type == ImportExportBase.CHOWDOWN: return Chowdown(request, export_type) if export_type == ImportExportBase.SAFFRON: return Saffron(request, export_type) if export_type == ImportExportBase.CHEFTAP: return ChefTap(request, export_type) if export_type == ImportExportBase.PEPPERPLATE: return Pepperplate(request, export_type) if export_type == ImportExportBase.DOMESTICA: return Domestica(request, export_type) if export_type == ImportExportBase.RECIPEKEEPER: return RecipeKeeper(request, export_type) if export_type == ImportExportBase.RECETTETEK: return RecetteTek(request, export_type) if export_type == ImportExportBase.RECIPESAGE: return RecipeSage(request, export_type) if export_type == ImportExportBase.REZKONV: return RezKonv(request, export_type) if export_type == ImportExportBase.MEALMASTER: return MealMaster(request, export_type) if export_type == ImportExportBase.OPENEATS: return OpenEats(request, export_type) if export_type == ImportExportBase.PLANTOEAT: return Plantoeat(request, export_type) if export_type == ImportExportBase.COOKBOOKAPP: return CookBookApp(request, export_type) if export_type == ImportExportBase.COPYMETHAT: return CopyMeThat(request, export_type) if export_type == ImportExportBase.PDF: return PDFexport(request, export_type) @group_required('user') def import_recipe(request): if request.space.max_recipes != 0 and Recipe.objects.filter(space=request.space).count() >= request.space.max_recipes: # TODO move to central helper function messages.add_message(request, messages.WARNING, _('You have reached the maximum number of recipes for your space.')) return HttpResponseRedirect(reverse('index')) if request.space.max_users != 0 and UserPreference.objects.filter(space=request.space).count() > request.space.max_users: messages.add_message(request, messages.WARNING, _('You have more users than allowed in your space.')) return HttpResponseRedirect(reverse('index')) if request.method == "POST": form = ImportForm(request.POST, request.FILES) if form.is_valid() and request.FILES != {}: try: integration = get_integration(request, form.cleaned_data['type']) il = ImportLog.objects.create(type=form.cleaned_data['type'], created_by=request.user, space=request.space) files = [] for f in request.FILES.getlist('files'): files.append({'file': BytesIO(f.read()), 'name': f.name}) t = threading.Thread(target=integration.do_import, args=[files, il, form.cleaned_data['duplicates']]) t.setDaemon(True) t.start() return JsonResponse({'import_id': [il.pk]}) except NotImplementedError: return JsonResponse( { 'error': True, 'msg': _('Importing is not implemented for this provider') }, status=400 ) else: form = ImportForm() return render(request, 'import.html', {'form': form}) @group_required('user') def export_recipe(request): if request.method == "POST": form = ExportForm(request.POST, space=request.space) if form.is_valid(): try: recipes = form.cleaned_data['recipes'] if form.cleaned_data['all']: recipes = Recipe.objects.filter(space=request.space, internal=True).all() integration = get_integration(request, form.cleaned_data['type']) el = ExportLog.objects.create(type=form.cleaned_data['type'], created_by=request.user, space=request.space) t = threading.Thread(target=integration.do_export, args=[recipes, el]) t.setDaemon(True) t.start() return JsonResponse({'export_id': el.pk}) except NotImplementedError: return JsonResponse( { 'error': True, 'msg': _('Importing is not implemented for this provider') }, status=400 ) else: form = ExportForm(space=request.space) recipe = request.GET.get('r') if recipe: if re.match(r'^([0-9])+$', recipe): if recipe := Recipe.objects.filter(pk=int(recipe), space=request.space).first(): form = ExportForm(initial={'recipes': recipe}, space=request.space) return render(request, 'export.html', {'form': form}) @group_required('user') def import_response(request, pk): return render(request, 'import_response.html', {'pk': pk}) @group_required('user') def export_response(request, pk): return render(request, 'export_response.html', {'pk': pk}) @group_required('user') def export_file(request, pk): cacheData = cache.get('export_file_'+str(pk)) if cacheData is None: el = ExportLog.objects.get(pk=pk) el.possibly_not_expired = False; el.save() return render(request, 'export_response.html', {'pk': pk}) response = HttpResponse(cacheData['file'], content_type='application/force-download') response['Content-Disposition'] = 'attachment; filename="'+cacheData['filename']+'"' return response