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

1import re 

2import threading 

3 

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 _ 

8 

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 

36 

37 

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) 

83 

84 

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

97 

98 integration = get_integration(request, form.cleaned_data['type']) 

99 

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.')}) 

102 

103 el = ExportLog.objects.create(type=form.cleaned_data['type'], created_by=request.user, space=request.space) 

104 

105 t = threading.Thread(target=integration.do_export, args=[recipes, el]) 

106 t.setDaemon(True) 

107 t.start() 

108 

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 

124 

125 return render(request, 'export.html', {'pk': pk}) 

126 

127 

128@group_required('user') 

129def import_response(request, pk): 

130 return render(request, 'import_response.html', {'pk': pk}) 

131 

132 

133@group_required('user') 

134def export_response(request, pk): 

135 return render(request, 'export_response.html', {'pk': pk}) 

136 

137 

138@group_required('user') 

139def export_file(request, pk): 

140 el = get_object_or_404(ExportLog, pk=pk, space=request.space) 

141 

142 cacheData = cache.get(f'export_file_{el.pk}') 

143 

144 if cacheData is None: 

145 el.possibly_not_expired = False 

146 el.save() 

147 return render(request, 'export_response.html', {'pk': pk}) 

148 

149 response = HttpResponse(cacheData['file'], content_type='application/force-download') 

150 response['Content-Disposition'] = 'attachment; filename="' + cacheData['filename'] + '"' 

151 return response