Coverage for cookbook/views/import_export.py: 39%
123 statements
« prev ^ index » next coverage.py v7.4.0, created at 2023-12-29 01:02 +0100
« prev ^ index » next coverage.py v7.4.0, created at 2023-12-29 01:02 +0100
1import re
2import threading
4from django.core.cache import cache
5from django.http import HttpResponse, JsonResponse
6from django.shortcuts import get_object_or_404, render
7from django.utils.translation import gettext as _
9from cookbook.forms import ExportForm, ImportExportBase
10from cookbook.helper.permission_helper import group_required
11from cookbook.helper.recipe_search import RecipeSearch
12from cookbook.integration.cheftap import ChefTap
13from cookbook.integration.chowdown import Chowdown
14from cookbook.integration.cookbookapp import CookBookApp
15from cookbook.integration.cookmate import Cookmate
16from cookbook.integration.copymethat import CopyMeThat
17from cookbook.integration.default import Default
18from cookbook.integration.domestica import Domestica
19from cookbook.integration.mealie import Mealie
20from cookbook.integration.mealmaster import MealMaster
21from cookbook.integration.melarecipes import MelaRecipes
22from cookbook.integration.nextcloud_cookbook import NextcloudCookbook
23from cookbook.integration.openeats import OpenEats
24from cookbook.integration.paprika import Paprika
25from cookbook.integration.pdfexport import PDFexport
26from cookbook.integration.pepperplate import Pepperplate
27from cookbook.integration.plantoeat import Plantoeat
28from cookbook.integration.recettetek import RecetteTek
29from cookbook.integration.recipekeeper import RecipeKeeper
30from cookbook.integration.recipesage import RecipeSage
31from cookbook.integration.rezeptsuitede import Rezeptsuitede
32from cookbook.integration.rezkonv import RezKonv
33from cookbook.integration.saffron import Saffron
34from cookbook.models import ExportLog, Recipe
35from recipes import settings
38def get_integration(request, export_type):
39 if export_type == ImportExportBase.DEFAULT:
40 return Default(request, export_type)
41 if export_type == ImportExportBase.PAPRIKA:
42 return Paprika(request, export_type)
43 if export_type == ImportExportBase.NEXTCLOUD:
44 return NextcloudCookbook(request, export_type)
45 if export_type == ImportExportBase.MEALIE:
46 return Mealie(request, export_type)
47 if export_type == ImportExportBase.CHOWDOWN:
48 return Chowdown(request, export_type)
49 if export_type == ImportExportBase.SAFFRON:
50 return Saffron(request, export_type)
51 if export_type == ImportExportBase.CHEFTAP:
52 return ChefTap(request, export_type)
53 if export_type == ImportExportBase.PEPPERPLATE:
54 return Pepperplate(request, export_type)
55 if export_type == ImportExportBase.DOMESTICA:
56 return Domestica(request, export_type)
57 if export_type == ImportExportBase.RECIPEKEEPER:
58 return RecipeKeeper(request, export_type)
59 if export_type == ImportExportBase.RECETTETEK:
60 return RecetteTek(request, export_type)
61 if export_type == ImportExportBase.RECIPESAGE:
62 return RecipeSage(request, export_type)
63 if export_type == ImportExportBase.REZKONV:
64 return RezKonv(request, export_type)
65 if export_type == ImportExportBase.MEALMASTER:
66 return MealMaster(request, export_type)
67 if export_type == ImportExportBase.OPENEATS:
68 return OpenEats(request, export_type)
69 if export_type == ImportExportBase.PLANTOEAT:
70 return Plantoeat(request, export_type)
71 if export_type == ImportExportBase.COOKBOOKAPP:
72 return CookBookApp(request, export_type)
73 if export_type == ImportExportBase.COPYMETHAT:
74 return CopyMeThat(request, export_type)
75 if export_type == ImportExportBase.PDF:
76 return PDFexport(request, export_type)
77 if export_type == ImportExportBase.MELARECIPES:
78 return MelaRecipes(request, export_type)
79 if export_type == ImportExportBase.COOKMATE:
80 return Cookmate(request, export_type)
81 if export_type == ImportExportBase.REZEPTSUITEDE:
82 return Rezeptsuitede(request, export_type)
85@group_required('user')
86def export_recipe(request):
87 if request.method == "POST":
88 form = ExportForm(request.POST, space=request.space)
89 if form.is_valid():
90 try:
91 recipes = form.cleaned_data['recipes']
92 if form.cleaned_data['all']:
93 recipes = Recipe.objects.filter(space=request.space, internal=True).all()
94 elif custom_filter := form.cleaned_data['custom_filter']:
95 search = RecipeSearch(request, filter=custom_filter)
96 recipes = search.get_queryset(Recipe.objects.filter(space=request.space, internal=True))
98 integration = get_integration(request, form.cleaned_data['type'])
100 if form.cleaned_data['type'] == ImportExportBase.PDF and not settings.ENABLE_PDF_EXPORT:
101 return JsonResponse({'error': _('The PDF Exporter is not enabled on this instance as it is still in an experimental state.')})
103 el = ExportLog.objects.create(type=form.cleaned_data['type'], created_by=request.user, space=request.space)
105 t = threading.Thread(target=integration.do_export, args=[recipes, el])
106 t.setDaemon(True)
107 t.start()
109 return JsonResponse({'export_id': el.pk})
110 except NotImplementedError:
111 return JsonResponse(
112 {
113 'error': True,
114 'msg': _('Importing is not implemented for this provider')
115 },
116 status=400
117 )
118 else:
119 pk = ''
120 recipe = request.GET.get('r')
121 if recipe:
122 if re.match(r'^([0-9])+$', recipe):
123 pk = Recipe.objects.filter(pk=int(recipe), space=request.space).first().pk
125 return render(request, 'export.html', {'pk': pk})
128@group_required('user')
129def import_response(request, pk):
130 return render(request, 'import_response.html', {'pk': pk})
133@group_required('user')
134def export_response(request, pk):
135 return render(request, 'export_response.html', {'pk': pk})
138@group_required('user')
139def export_file(request, pk):
140 el = get_object_or_404(ExportLog, pk=pk, space=request.space)
142 cacheData = cache.get(f'export_file_{el.pk}')
144 if cacheData is None:
145 el.possibly_not_expired = False
146 el.save()
147 return render(request, 'export_response.html', {'pk': pk})
149 response = HttpResponse(cacheData['file'], content_type='application/force-download')
150 response['Content-Disposition'] = 'attachment; filename="' + cacheData['filename'] + '"'
151 return response