Files
mealie/mealie/services/recipe/template_service.py
2026-02-03 16:43:42 -06:00

109 lines
3.4 KiB
Python

import enum
from pathlib import Path
from zipfile import ZipFile
from mealie.schema.recipe import Recipe
from mealie.schema.recipe.recipe_image_types import RecipeImageTypes
from mealie.services._base_service import BaseService
class TemplateType(enum.StrEnum):
json = "json"
zip = "zip"
class TemplateService(BaseService):
def __init__(self, temp: Path | None = None) -> None:
"""Creates a template service that can be used for multiple template generations
A temporary directory must be provided as a place holder for where to render all templates
Args:
temp (Path): [description]
"""
self.temp = temp
self.types = TemplateType
super().__init__()
@property
def templates(self) -> dict[str, list[str]]:
"""
Returns a list of all templates available to render.
"""
return {
TemplateType.json.value: ["raw"],
TemplateType.zip.value: ["zip"],
}
def __check_temp(self, method) -> None:
"""
Checks if the temporary directory was provided on initialization
"""
if self.temp is None:
raise ValueError(f"Temporary directory must be provided for method {method.__name__}")
def template_type(self, template: str) -> TemplateType:
# Determine Type:
t_type = None
for key, value in self.templates.items():
if template in value:
t_type = key
break
if t_type is None:
raise ValueError(f"Template '{template}' not found.")
return TemplateType(t_type)
def render(self, recipe: Recipe, template: str) -> Path:
"""
Renders a TemplateType in a temporary directory and returns the path to the file.
Args:
t_type (TemplateType): The type of template to render
recipe (Recipe): The recipe to render
template (str): The template to render
"""
t_type = self.template_type(template)
if t_type == TemplateType.json:
return self._render_json(recipe)
if t_type == TemplateType.zip:
return self._render_zip(recipe)
raise ValueError(f"Template Type '{t_type}' not found.")
def _render_json(self, recipe: Recipe) -> Path:
"""
Renders a JSON file in a temporary directory and returns
the path to the file.
"""
self.__check_temp(self._render_json)
if self.temp is None:
raise ValueError("Temporary directory must be provided for method _render_json")
save_path = self.temp.joinpath(f"{recipe.slug}.json")
with open(save_path, "w") as f:
f.write(recipe.model_dump_json(indent=4, by_alias=True))
return save_path
def _render_zip(self, recipe: Recipe) -> Path:
self.__check_temp(self._render_zip)
image_asset = recipe.image_dir.joinpath(RecipeImageTypes.original.value)
if self.temp is None:
raise ValueError("Temporary directory must be provided for method _render_zip")
zip_temp = self.temp.joinpath(f"{recipe.slug}.zip")
with ZipFile(zip_temp, "w") as myzip:
myzip.writestr(f"{recipe.slug}.json", recipe.model_dump_json())
if image_asset.is_file():
myzip.write(image_asset, arcname=image_asset.name)
return zip_temp