TandoorRecipes/cookbook/views/import_export.py
2022-02-15 06:42:57 -06:00

181 lines
7.5 KiB
Python

import re
import threading
from io import BytesIO
from django.contrib import messages
from django.core.cache import cache
from django.http import HttpResponse, HttpResponseRedirect, JsonResponse
from django.shortcuts import get_object_or_404, render
from django.urls import reverse
from django.utils.translation import gettext as _
from cookbook.forms import ExportForm, ImportExportBase, ImportForm
from cookbook.helper.permission_helper import group_required
from cookbook.integration.cheftap import ChefTap
from cookbook.integration.chowdown import Chowdown
from cookbook.integration.cookbookapp import CookBookApp
from cookbook.integration.copymethat import CopyMeThat
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.pdfexport import PDFexport
from cookbook.integration.pepperplate import Pepperplate
from cookbook.integration.plantoeat import Plantoeat
from cookbook.integration.recettetek import RecetteTek
from cookbook.integration.recipekeeper import RecipeKeeper
from cookbook.integration.recipesage import RecipeSage
from cookbook.integration.rezkonv import RezKonv
from cookbook.integration.saffron import Saffron
from cookbook.models import ExportLog, ImportLog, Recipe, 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'])
if form.cleaned_data['type'] == ImportExportBase.PDF and not settings.ENABLE_PDF_EXPORT:
return JsonResponse({'error': _('The PDF Exporter is not enabled on this instance as it is still in an experimental state.')})
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:
pk = ''
recipe = request.GET.get('r')
if recipe:
if re.match(r'^([0-9])+$', recipe):
pk = Recipe.objects.filter(pk=int(recipe), space=request.space).first().pk
return render(request, 'export.html', {'pk': pk})
@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):
el = get_object_or_404(ExportLog, pk=pk, space=request.space)
cacheData = cache.get(f'export_file_{el.pk}')
if cacheData is None:
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