improved paprika importer
This commit is contained in:
parent
48c90c483a
commit
fe1ddf1237
@ -84,7 +84,7 @@ class Integration:
|
|||||||
try:
|
try:
|
||||||
self.files = files
|
self.files = files
|
||||||
for f in files:
|
for f in files:
|
||||||
if '.zip' in f.name:
|
if '.zip' in f.name or '.paprikarecipes' in f.name:
|
||||||
import_zip = ZipFile(f.file)
|
import_zip = ZipFile(f.file)
|
||||||
for z in import_zip.filelist:
|
for z in import_zip.filelist:
|
||||||
if self.import_file_name_filter(z):
|
if self.import_file_name_filter(z):
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
import base64
|
||||||
import json
|
import json
|
||||||
import re
|
import re
|
||||||
from io import BytesIO
|
from io import BytesIO
|
||||||
@ -6,51 +7,39 @@ from zipfile import ZipFile
|
|||||||
import microdata
|
import microdata
|
||||||
from bs4 import BeautifulSoup
|
from bs4 import BeautifulSoup
|
||||||
|
|
||||||
|
from cookbook.helper.ingredient_parser import parse
|
||||||
from cookbook.helper.recipe_url_import import find_recipe_json
|
from cookbook.helper.recipe_url_import import find_recipe_json
|
||||||
from cookbook.integration.integration import Integration
|
from cookbook.integration.integration import Integration
|
||||||
from cookbook.models import Recipe, Step, Food, Ingredient, Unit
|
from cookbook.models import Recipe, Step, Food, Ingredient, Unit
|
||||||
|
import gzip
|
||||||
|
|
||||||
|
|
||||||
class Paprika(Integration):
|
class Paprika(Integration):
|
||||||
|
|
||||||
def import_file_name_filter(self, zip_info_object):
|
|
||||||
print("testing", zip_info_object.filename)
|
|
||||||
return re.match(r'^Recipes/([A-Za-z\s])+.html$', zip_info_object.filename)
|
|
||||||
|
|
||||||
def get_file_from_recipe(self, recipe):
|
def get_file_from_recipe(self, recipe):
|
||||||
raise NotImplementedError('Method not implemented in storage integration')
|
raise NotImplementedError('Method not implemented in storage integration')
|
||||||
|
|
||||||
def get_recipe_from_file(self, file):
|
def get_recipe_from_file(self, file):
|
||||||
html_text = file.getvalue().decode("utf-8")
|
with gzip.open(file, 'r') as recipe_zip:
|
||||||
|
recipe_json = json.loads(recipe_zip.read().decode("utf-8"))
|
||||||
|
|
||||||
|
recipe = Recipe.objects.create(
|
||||||
|
name=recipe_json['name'].strip(), description=recipe_json['description'].strip(),
|
||||||
|
created_by=self.request.user, internal=True, space=self.request.space)
|
||||||
|
|
||||||
items = microdata.get_items(html_text)
|
|
||||||
for i in items:
|
|
||||||
md_json = json.loads(i.json())
|
|
||||||
if 'schema.org/Recipe' in str(md_json['type']):
|
|
||||||
recipe_json = find_recipe_json(md_json['properties'], '', space=self.request.space)
|
|
||||||
recipe = Recipe.objects.create(name=recipe_json['name'].strip(), created_by=self.request.user, internal=True, space=self.request.space)
|
|
||||||
step = Step.objects.create(
|
step = Step.objects.create(
|
||||||
instruction=recipe_json['recipeInstructions']
|
instruction=recipe_json['directions'] + '\n\n' + recipe_json['nutritional_info']
|
||||||
)
|
)
|
||||||
|
|
||||||
for ingredient in recipe_json['recipeIngredient']:
|
for ingredient in recipe_json['ingredients'].split('\n'):
|
||||||
f, created = Food.objects.get_or_create(name=ingredient['ingredient']['text'], space=self.request.space)
|
amount, unit, ingredient, note = parse(ingredient)
|
||||||
u, created = Unit.objects.get_or_create(name=ingredient['unit']['text'], space=self.request.space)
|
f, created = Food.objects.get_or_create(name=ingredient, space=self.request.space)
|
||||||
|
u, created = Unit.objects.get_or_create(name=unit, space=self.request.space)
|
||||||
step.ingredients.add(Ingredient.objects.create(
|
step.ingredients.add(Ingredient.objects.create(
|
||||||
food=f, unit=u, amount=ingredient['amount'], note=ingredient['note']
|
food=f, unit=u, amount=amount, note=note
|
||||||
))
|
))
|
||||||
|
|
||||||
recipe.steps.add(step)
|
recipe.steps.add(step)
|
||||||
|
|
||||||
soup = BeautifulSoup(html_text, "html.parser")
|
self.import_recipe_image(recipe, BytesIO(base64.b64decode(recipe_json['photo_data'])))
|
||||||
image = soup.find('img')
|
|
||||||
image_name = image.attrs['src'].strip().replace('Images/', '')
|
|
||||||
|
|
||||||
for f in self.files:
|
|
||||||
if '.zip' in f.name:
|
|
||||||
import_zip = ZipFile(f.file)
|
|
||||||
for z in import_zip.filelist:
|
|
||||||
if re.match(f'^Recipes/Images/{image_name}$', z.filename):
|
|
||||||
self.import_recipe_image(recipe, BytesIO(import_zip.read(z.filename)))
|
|
||||||
|
|
||||||
return recipe
|
return recipe
|
||||||
|
@ -1,6 +1,10 @@
|
|||||||
This application features a very versatile import and export feature in order
|
This application features a very versatile import and export feature in order
|
||||||
to offer the best experience possible and allow you to freely choose where your data goes.
|
to offer the best experience possible and allow you to freely choose where your data goes.
|
||||||
|
|
||||||
|
!!! warning "WIP"
|
||||||
|
The Module is relatively new. There is a know issue with [Timeouts](https://github.com/vabene1111/recipes/issues/417) on large exports.
|
||||||
|
A fix is being developed and will likely be released with the next version.
|
||||||
|
|
||||||
The Module is build with maximum flexibility and expandability in mind and allows to easily add new
|
The Module is build with maximum flexibility and expandability in mind and allows to easily add new
|
||||||
integrations to allow you to both import and export your recipes into whatever format you desire.
|
integrations to allow you to both import and export your recipes into whatever format you desire.
|
||||||
|
|
||||||
@ -14,6 +18,19 @@ if your favorite one is missing.
|
|||||||
Because of this importing as many formats as possible is prioritized over exporting.
|
Because of this importing as many formats as possible is prioritized over exporting.
|
||||||
Exporter for the different formats will follow over time.
|
Exporter for the different formats will follow over time.
|
||||||
|
|
||||||
|
Overview of the capabilities of the different integrations.
|
||||||
|
|
||||||
|
| Integration | Import | Export | Images |
|
||||||
|
| ----------- | ------ | ------ | ------ |
|
||||||
|
| Default | ✔️ | ✔️ | ✔️ |
|
||||||
|
| Nextcloud | ✔️ | ⌚ | ✔️ |
|
||||||
|
| Mealie | ✔️ | ⌚ | ✔️ |
|
||||||
|
| Chowdown | ✔️ | ⌚ | ✔️ |
|
||||||
|
| Safron | ✔️ | ⌚ | ❌ |
|
||||||
|
| Paprika | ✔️ | ⌚ | ✔️ |
|
||||||
|
|
||||||
|
✔ = implemented, ❌ = not implemented and not possible, ⌚ = not yet implemented
|
||||||
|
|
||||||
## Default
|
## Default
|
||||||
The default integration is the build in (and preferred) way to import and export recipes.
|
The default integration is the build in (and preferred) way to import and export recipes.
|
||||||
It is maintained with new fields added and contains all data to transfer your recipes from one installation to another.
|
It is maintained with new fields added and contains all data to transfer your recipes from one installation to another.
|
||||||
@ -88,22 +105,7 @@ Then simply upload the entire `.zip` file to the importer.
|
|||||||
Safron exports do not contain any images. They will be lost during import.
|
Safron exports do not contain any images. They will be lost during import.
|
||||||
|
|
||||||
## Paprika
|
## Paprika
|
||||||
Paprika can create two types of export. The first is a proprietary `.paprikarecipes` file in some kind of binarized format.
|
A Paprika export contains a folder with a html representation of your recipes and a `.paprikarecipes` file.
|
||||||
The second one is HTML files containing at least a bit of microdata.
|
|
||||||
|
|
||||||
If you want to import your Paprika recipes follow these steps
|
The `.paprikarecipes` file is basically just a zip with gzipped contents. Simply upload the whole file and import
|
||||||
|
all your recipes.
|
||||||
1. create a html export
|
|
||||||
2. Create a `.zip` file from the `Recipes` folder (next to the `index.html`) the structure should look like this
|
|
||||||
```
|
|
||||||
Recipes.zip/
|
|
||||||
└── Recipes/
|
|
||||||
├── recipe one.html
|
|
||||||
├── recipe two.thml
|
|
||||||
└── Images/
|
|
||||||
├── 5D5E09CD-8F88-4F61-8121-0727DD3E0E89/
|
|
||||||
│ └── 5D5E09CD-8F88-4F61-8121-0727DD3E0E89.jpg
|
|
||||||
└── 7CEE2AC6-DF60-4464-9B61-4F5E347EB90C/
|
|
||||||
└── 7CEE2AC6-DF60-4464-9B61-4F5E347EB90C.jpg
|
|
||||||
```
|
|
||||||
3. Upload the zip file in the import module and import it
|
|
Loading…
Reference in New Issue
Block a user