Skip to content

Commit

Permalink
fix: Recipe Keeper Errors and Other Safari Issues (#3712)
Browse files Browse the repository at this point in the history
Co-authored-by: Kuchenpirat <24235032+Kuchenpirat@users.noreply.github.com>
  • Loading branch information
michael-genson and Kuchenpirat authored Jun 7, 2024
1 parent eab7c0d commit 4634ad5
Show file tree
Hide file tree
Showing 9 changed files with 101 additions and 31 deletions.
48 changes: 24 additions & 24 deletions frontend/pages/group/migrations.vue
Original file line number Diff line number Diff line change
Expand Up @@ -132,14 +132,14 @@ export default defineComponent({
text: i18n.tc("migration.plantoeat.title"),
value: MIGRATIONS.plantoeat,
},
{
text: i18n.tc("migration.tandoor.title"),
value: MIGRATIONS.tandoor,
},
{
text: i18n.tc("migration.recipekeeper.title"),
value: MIGRATIONS.recipekeeper,
},
{
text: i18n.tc("migration.tandoor.title"),
value: MIGRATIONS.tandoor,
},
];
const _content = {
[MIGRATIONS.mealie]: {
Expand Down Expand Up @@ -312,6 +312,26 @@ export default defineComponent({
}
],
},
[MIGRATIONS.recipekeeper]: {
text: i18n.tc("migration.recipekeeper.description-long"),
acceptedFileType: ".zip",
tree: [
{
id: 1,
icon: $globals.icons.zip,
name: "recipekeeperhtml.zip",
children: [
{ id: 2, name: "recipes.html", icon: $globals.icons.codeJson },
{ id: 3, name: "images", icon: $globals.icons.folderOutline,
children: [
{ id: 4, name: "image1.jpg", icon: $globals.icons.fileImage },
{ id: 5, name: "image2.jpg", icon: $globals.icons.fileImage },
]
},
],
}
],
},
[MIGRATIONS.tandoor]: {
text: i18n.tc("migration.tandoor.description-long"),
acceptedFileType: ".zip",
Expand Down Expand Up @@ -352,26 +372,6 @@ export default defineComponent({
}
],
},
[MIGRATIONS.recipekeeper]: {
text: i18n.tc("migration.recipekeeper.description-long"),
acceptedFileType: ".zip",
tree: [
{
id: 1,
icon: $globals.icons.zip,
name: "recipekeeperhtml.zip",
children: [
{ id: 2, name: "recipes.html", icon: $globals.icons.codeJson },
{ id: 3, name: "images", icon: $globals.icons.folderOutline,
children: [
{ id: 4, name: "image1.jpeg", icon: $globals.icons.fileImage },
{ id: 5, name: "image2.jpeg", icon: $globals.icons.fileImage },
]
},
],
}
],
},
};
function setFileObject(fileObject: File) {
Expand Down
22 changes: 22 additions & 0 deletions mealie/services/migrations/_migration_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,28 @@ def __init__(

super().__init__()

@classmethod
def get_zip_base_path(cls, path: Path) -> Path:
# Safari mangles our ZIP structure and adds a "__MACOSX" directory at the root along with
# an arbitrarily-named directory containing the actual contents. So, if we find a dunder directory
# at the root (i.e. __MACOSX) we traverse down the first non-dunder directory and assume this is the base.
# We assume migration exports never contain a directory that starts with "__".
normal_dirs: list[Path] = []
dunder_dirs: list[Path] = []
for dir in path.iterdir():
if not dir.is_dir():
continue

if dir.name.startswith("__"):
dunder_dirs.append(dir)
else:
normal_dirs.append(dir)

if len(normal_dirs) == 1 and len(dunder_dirs) == 1:
return normal_dirs[0]
else:
return path

def _migrate(self) -> None:
raise NotImplementedError

Expand Down
14 changes: 13 additions & 1 deletion mealie/services/migrations/chowdown.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,24 @@ def __init__(self, **kwargs):
MigrationAlias(key="tags", alias="tags", func=split_by_comma),
]

@classmethod
def get_zip_base_path(cls, path: Path) -> Path:
potential_path = super().get_zip_base_path(path)
if path == potential_path:
return path

# make sure we didn't accidentally open a recipe dir
if (potential_path / "recipe.json").exists():
return path
else:
return potential_path

def _migrate(self) -> None:
with tempfile.TemporaryDirectory() as tmpdir:
with zipfile.ZipFile(self.archive) as zip_file:
zip_file.extractall(tmpdir)

temp_path = Path(tmpdir)
temp_path = self.get_zip_base_path(Path(tmpdir))

chow_dir = next(temp_path.iterdir())
image_dir = temp_path.joinpath(chow_dir, "images")
Expand Down
2 changes: 1 addition & 1 deletion mealie/services/migrations/copymethat.py
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ def _migrate(self) -> None:
with zipfile.ZipFile(self.archive) as zip_file:
zip_file.extractall(tmpdir)

source_dir = Path(tmpdir)
source_dir = self.get_zip_base_path(Path(tmpdir))

recipes_as_dicts: list[dict] = []
for recipes_data_file in source_dir.glob("*.html"):
Expand Down
14 changes: 13 additions & 1 deletion mealie/services/migrations/mealie_alpha.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,18 @@ def __init__(self, **kwargs):
MigrationAlias(key="tags", alias="tags", func=split_by_comma),
]

@classmethod
def get_zip_base_path(cls, path: Path) -> Path:
potential_path = super().get_zip_base_path(path)
if path == potential_path:
return path

# make sure we didn't accidentally open the "recipes" dir
if potential_path.name == "recipes":
return path
else:
return potential_path

def _convert_to_new_schema(self, recipe: dict) -> Recipe:
if recipe.get("categories", False):
recipe["recipeCategory"] = recipe.get("categories")
Expand Down Expand Up @@ -55,7 +67,7 @@ def _migrate(self) -> None:
with zipfile.ZipFile(self.archive) as zip_file:
zip_file.extractall(tmpdir)

temp_path = Path(tmpdir)
temp_path = self.get_zip_base_path(Path(tmpdir))
recipe_lookup: dict[str, Path] = {}

recipes: list[Recipe] = []
Expand Down
15 changes: 14 additions & 1 deletion mealie/services/migrations/nextcloud.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,18 @@ def __init__(self, **kwargs):
MigrationAlias(key="performTime", alias="cookTime", func=parse_iso8601_duration),
]

@classmethod
def get_zip_base_path(cls, path: Path) -> Path:
potential_path = super().get_zip_base_path(path)
if path == potential_path:
return path

# make sure we didn't accidentally open a recipe dir
if (potential_path / "recipe.json").exists():
return path
else:
return potential_path

def _migrate(self) -> None:
# Unzip File into temp directory

Expand All @@ -65,7 +77,8 @@ def _migrate(self) -> None:
with zipfile.ZipFile(self.archive) as zip_file:
zip_file.extractall(tmpdir)

potential_recipe_dirs = glob_walker(Path(tmpdir), glob_str="**/[!.]*.json", return_parent=True)
base_dir = self.get_zip_base_path(Path(tmpdir))
potential_recipe_dirs = glob_walker(base_dir, glob_str="**/[!.]*.json", return_parent=True)
nextcloud_dirs = {y.slug: y for x in potential_recipe_dirs if (y := NextcloudDir.from_dir(x))}

all_recipes = []
Expand Down
15 changes: 13 additions & 2 deletions mealie/services/migrations/recipekeeper.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,17 @@
from .utils.migration_helpers import import_image, parse_iso8601_duration


def clean_instructions(instructions: list[str]) -> list[str]:
try:
for i, instruction in enumerate(instructions):
if instruction.startswith(f"{i + 1}. "):
instructions[i] = instruction.removeprefix(f"{i + 1}. ")

return instructions
except Exception:
return instructions


def parse_recipe_div(recipe, image_path):
meta = {}
for item in recipe.find_all(lambda x: x.has_attr("itemprop")):
Expand Down Expand Up @@ -59,7 +70,7 @@ def __init__(self, **kwargs):
key="recipeIngredient",
alias="recipeIngredients",
),
MigrationAlias(key="recipeInstructions", alias="recipeDirections"),
MigrationAlias(key="recipeInstructions", alias="recipeDirections", func=clean_instructions),
MigrationAlias(key="performTime", alias="cookTime", func=parse_iso8601_duration),
MigrationAlias(key="prepTime", alias="prepTime", func=parse_iso8601_duration),
MigrationAlias(key="image", alias="photo0"),
Expand All @@ -77,7 +88,7 @@ def _migrate(self) -> None:
with zipfile.ZipFile(self.archive) as zip_file:
zip_file.extractall(tmpdir)

source_dir = Path(tmpdir) / "recipekeeperhtml"
source_dir = self.get_zip_base_path(Path(tmpdir))

recipes_as_dicts: list[dict] = []
with open(source_dir / "recipes.html") as fp:
Expand Down
2 changes: 1 addition & 1 deletion mealie/services/migrations/tandoor.py
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ def _migrate(self) -> None:
with zipfile.ZipFile(self.archive) as zip_file:
zip_file.extractall(tmpdir)

source_dir = Path(tmpdir)
source_dir = self.get_zip_base_path(Path(tmpdir))

recipes_as_dicts: list[dict] = []
for i, recipe_zip_file in enumerate(source_dir.glob("*.zip")):
Expand Down
Binary file modified tests/data/migrations/recipekeeper.zip
Binary file not shown.

0 comments on commit 4634ad5

Please sign in to comment.