mirror of
https://github.com/hay-kot/mealie.git
synced 2025-08-22 06:23:34 -07:00
move images to /recipes/{slug}/images
This commit is contained in:
parent
38d704a5bc
commit
0a6a29a004
15 changed files with 121 additions and 128 deletions
|
@ -10,8 +10,8 @@
|
|||
encode gzip
|
||||
uri strip_suffix /
|
||||
|
||||
handle_path /api/recipes/image/* {
|
||||
root * /app/data/img/
|
||||
handle_path /api/recipes/media/* {
|
||||
root * /app/data/recipes/
|
||||
file_server
|
||||
}
|
||||
|
||||
|
|
|
@ -14,9 +14,9 @@ const recipeURLs = {
|
|||
recipe: slug => prefix + slug,
|
||||
update: slug => prefix + slug,
|
||||
delete: slug => prefix + slug,
|
||||
createAsset: slug => `${prefix}media/${slug}/assets`,
|
||||
recipeImage: slug => `${prefix}${slug}/image`,
|
||||
updateImage: slug => `${prefix}${slug}/image`,
|
||||
createAsset: slug => `${prefix}${slug}/asset`,
|
||||
};
|
||||
|
||||
export const recipeAPI = {
|
||||
|
@ -84,7 +84,7 @@ export const recipeAPI = {
|
|||
fd.append("extension", fileObject.name.split(".").pop());
|
||||
fd.append("name", name);
|
||||
fd.append("icon", icon);
|
||||
let response = apiReq.post(recipeURLs.createAsset(recipeSlug), fd);
|
||||
const response = apiReq.post(recipeURLs.createAsset(recipeSlug), fd);
|
||||
return response;
|
||||
},
|
||||
|
||||
|
@ -135,14 +135,14 @@ export const recipeAPI = {
|
|||
},
|
||||
|
||||
recipeImage(recipeSlug) {
|
||||
return `/api/recipes/image/${recipeSlug}/original.webp`;
|
||||
return `/api/recipes/media/${recipeSlug}/image/original.webp`;
|
||||
},
|
||||
|
||||
recipeSmallImage(recipeSlug) {
|
||||
return `/api/recipes/image/${recipeSlug}/min-original.webp`;
|
||||
return `/api/recipes/media/${recipeSlug}/image/min-original.webp`;
|
||||
},
|
||||
|
||||
recipeTinyImage(recipeSlug) {
|
||||
return `/api/recipes/image/${recipeSlug}/tiny-original.webp`;
|
||||
return `/api/recipes/media/${recipeSlug}/image/tiny-original.webp`;
|
||||
},
|
||||
};
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
v-if="!edit"
|
||||
color="primary"
|
||||
icon
|
||||
:href="`/api/recipes/${slug}/asset?file_name=${item.fileName}`"
|
||||
:href="`/api/recipes/media/${slug}/assets/${item.fileName}`"
|
||||
target="_blank"
|
||||
top
|
||||
>
|
||||
|
@ -135,7 +135,7 @@ export default {
|
|||
this.value.splice(index, 1);
|
||||
},
|
||||
copyLink(name, fileName) {
|
||||
const copyText = ``;
|
||||
const copyText = ``;
|
||||
navigator.clipboard.writeText(copyText).then(
|
||||
() => console.log("Copied", copyText),
|
||||
() => console.log("Copied Failed", copyText)
|
||||
|
|
|
@ -3,6 +3,7 @@ import shutil
|
|||
|
||||
from fastapi import APIRouter, Depends, File, HTTPException, UploadFile, status
|
||||
from mealie.core.config import app_dirs
|
||||
from mealie.core.root_logger import get_logger
|
||||
from mealie.core.security import create_file_token
|
||||
from mealie.db.db_setup import generate_session
|
||||
from mealie.routes.deps import get_current_user
|
||||
|
@ -12,6 +13,7 @@ from mealie.services.backups.exports import backup_all
|
|||
from sqlalchemy.orm.session import Session
|
||||
|
||||
router = APIRouter(prefix="/api/backups", tags=["Backups"], dependencies=[Depends(get_current_user)])
|
||||
logger = get_logger()
|
||||
|
||||
|
||||
@router.get("/available", response_model=Imports)
|
||||
|
@ -44,7 +46,8 @@ def export_database(data: BackupJob, session: Session = Depends(generate_session
|
|||
export_groups=data.options.groups,
|
||||
)
|
||||
return {"export_path": export_path}
|
||||
except Exception:
|
||||
except Exception as e:
|
||||
logger.error(e)
|
||||
raise HTTPException(status.HTTP_500_INTERNAL_SERVER_ERROR)
|
||||
|
||||
|
||||
|
|
|
@ -88,7 +88,7 @@ def get_todays_image(session: Session = Depends(generate_session), group_name: s
|
|||
recipe = get_todays_meal(session, group_in_db)
|
||||
|
||||
if recipe:
|
||||
recipe_image = image.read_image(recipe.slug, image_type=image.IMG_OPTIONS.ORIGINAL_IMAGE)
|
||||
recipe_image = recipe.image_dir.joinpath(image.ImageOptions.ORIGINAL_IMAGE)
|
||||
else:
|
||||
raise HTTPException(status.HTTP_404_NOT_FOUND)
|
||||
if recipe_image:
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
from fastapi import APIRouter
|
||||
from mealie.routes.recipe import all_recipe_routes, category_routes, recipe_assets, recipe_crud_routes, tag_routes
|
||||
from mealie.routes.recipe import all_recipe_routes, category_routes, recipe_crud_routes, recipe_media, tag_routes
|
||||
|
||||
router = APIRouter()
|
||||
|
||||
router.include_router(all_recipe_routes.router)
|
||||
router.include_router(recipe_crud_routes.router)
|
||||
router.include_router(recipe_assets.router)
|
||||
router.include_router(recipe_media.router)
|
||||
router.include_router(category_routes.router)
|
||||
router.include_router(tag_routes.router)
|
||||
|
|
|
@ -4,7 +4,8 @@ from mealie.db.database import db
|
|||
from mealie.db.db_setup import generate_session
|
||||
from mealie.routes.deps import get_current_user
|
||||
from mealie.schema.recipe import Recipe, RecipeURLIn
|
||||
from mealie.services.image.image import delete_image, rename_image, scrape_image, write_image
|
||||
from mealie.services.image.image import scrape_image, write_image
|
||||
from mealie.services.recipe.asset import check_asset
|
||||
from mealie.services.scraper.scraper import create_from_url
|
||||
from sqlalchemy.orm.session import Session
|
||||
|
||||
|
@ -58,7 +59,7 @@ def update_recipe(
|
|||
print(recipe.assets)
|
||||
|
||||
if recipe_slug != recipe.slug:
|
||||
rename_image(original_slug=recipe_slug, new_slug=recipe.slug)
|
||||
check_asset(original_slug=recipe_slug, recipe=recipe)
|
||||
|
||||
return recipe
|
||||
|
||||
|
@ -76,7 +77,7 @@ def patch_recipe(
|
|||
session, recipe_slug, new_data=data.dict(exclude_unset=True, exclude_defaults=True)
|
||||
)
|
||||
if recipe_slug != recipe.slug:
|
||||
rename_image(original_slug=recipe_slug, new_slug=recipe.slug)
|
||||
check_asset(original_slug=recipe_slug, recipe=recipe)
|
||||
|
||||
return recipe
|
||||
|
||||
|
@ -91,7 +92,6 @@ def delete_recipe(
|
|||
|
||||
try:
|
||||
delete_data = db.recipes.delete(session, recipe_slug)
|
||||
delete_image(recipe_slug)
|
||||
|
||||
return delete_data
|
||||
except Exception:
|
||||
|
|
|
@ -3,7 +3,6 @@ from enum import Enum
|
|||
|
||||
from fastapi import APIRouter, Depends, File, Form, HTTPException, status
|
||||
from fastapi.datastructures import UploadFile
|
||||
from mealie.core.config import app_dirs
|
||||
from mealie.db.database import db
|
||||
from mealie.db.db_setup import generate_session
|
||||
from mealie.routes.deps import get_current_user
|
||||
|
@ -12,7 +11,7 @@ from slugify import slugify
|
|||
from sqlalchemy.orm.session import Session
|
||||
from starlette.responses import FileResponse
|
||||
|
||||
router = APIRouter(prefix="/api/recipes", tags=["Recipe Media"])
|
||||
router = APIRouter(prefix="/api/recipes/media", tags=["Recipe Media"])
|
||||
|
||||
|
||||
class ImageType(str, Enum):
|
||||
|
@ -21,11 +20,12 @@ class ImageType(str, Enum):
|
|||
tiny = "tiny-original.webp"
|
||||
|
||||
|
||||
@router.get("/image/{recipe_slug}/{file_name}")
|
||||
@router.get("/{recipe_slug}/image/{file_name}")
|
||||
async def get_recipe_img(recipe_slug: str, file_name: ImageType = ImageType.original):
|
||||
"""Takes in a recipe slug, returns the static image. This route is proxied in the docker image
|
||||
and should not hit the API in production"""
|
||||
recipe_image = app_dirs.IMG_DIR.joinpath(recipe_slug, file_name.value)
|
||||
recipe_image = Recipe(slug=recipe_slug).image_dir.joinpath(file_name.value)
|
||||
|
||||
if recipe_image:
|
||||
return FileResponse(recipe_image)
|
||||
else:
|
||||
|
@ -33,13 +33,17 @@ async def get_recipe_img(recipe_slug: str, file_name: ImageType = ImageType.orig
|
|||
|
||||
|
||||
@router.get("/{recipe_slug}/assets/{file_name}")
|
||||
async def get_recipe_asset(recipe_slug, file_name: str):
|
||||
async def get_recipe_asset(recipe_slug: str, file_name: str):
|
||||
""" Returns a recipe asset """
|
||||
file = app_dirs.RECIPE_DATA_DIR.joinpath(recipe_slug, file_name)
|
||||
return FileResponse(file)
|
||||
file = Recipe(slug=recipe_slug).asset_dir.joinpath(file_name)
|
||||
|
||||
try:
|
||||
return FileResponse(file)
|
||||
except Exception:
|
||||
raise HTTPException(status.HTTP_404_NOT_FOUND)
|
||||
|
||||
|
||||
@router.post("/{recipe_slug}/asset", response_model=RecipeAsset)
|
||||
@router.post("/{recipe_slug}/assets", response_model=RecipeAsset)
|
||||
def upload_recipe_asset(
|
||||
recipe_slug: str,
|
||||
name: str = Form(...),
|
||||
|
@ -52,8 +56,7 @@ def upload_recipe_asset(
|
|||
""" Upload a file to store as a recipe asset """
|
||||
file_name = slugify(name) + "." + extension
|
||||
asset_in = RecipeAsset(name=name, icon=icon, file_name=file_name)
|
||||
dest = app_dirs.RECIPE_DATA_DIR.joinpath(recipe_slug, file_name)
|
||||
dest.parent.mkdir(exist_ok=True, parents=True)
|
||||
dest = Recipe(slug=recipe_slug).asset_dir.joinpath(file_name)
|
||||
|
||||
with dest.open("wb") as buffer:
|
||||
shutil.copyfileobj(file.file, buffer)
|
|
@ -1,7 +1,9 @@
|
|||
import datetime
|
||||
from pathlib import Path
|
||||
from typing import Any, Optional
|
||||
|
||||
from fastapi_camelcase import CamelModel
|
||||
from mealie.core.config import app_dirs
|
||||
from mealie.db.models.recipe.recipe import RecipeModel
|
||||
from pydantic import BaseModel, Field, validator
|
||||
from pydantic.utils import GetterDict
|
||||
|
@ -58,8 +60,8 @@ class Nutrition(CamelModel):
|
|||
|
||||
class RecipeSummary(CamelModel):
|
||||
id: Optional[int]
|
||||
name: str
|
||||
slug: Optional[str] = ""
|
||||
name: Optional[str]
|
||||
slug: str = ""
|
||||
image: Optional[Any]
|
||||
|
||||
description: Optional[str]
|
||||
|
@ -98,6 +100,28 @@ class Recipe(RecipeSummary):
|
|||
org_url: Optional[str] = Field(None, alias="orgURL")
|
||||
extras: Optional[dict] = {}
|
||||
|
||||
@staticmethod
|
||||
def directory_from_slug(slug) -> Path:
|
||||
return app_dirs.RECIPE_DATA_DIR.joinpath(slug)
|
||||
|
||||
@property
|
||||
def directory(self) -> Path:
|
||||
dir = app_dirs.RECIPE_DATA_DIR.joinpath(self.slug)
|
||||
dir.mkdir(exist_ok=True, parents=True)
|
||||
return dir
|
||||
|
||||
@property
|
||||
def asset_dir(self) -> Path:
|
||||
dir = self.directory.joinpath("assets")
|
||||
dir.mkdir(exist_ok=True, parents=True)
|
||||
return dir
|
||||
|
||||
@property
|
||||
def image_dir(self) -> Path:
|
||||
dir = self.directory.joinpath("images")
|
||||
dir.mkdir(exist_ok=True, parents=True)
|
||||
return dir
|
||||
|
||||
class Config:
|
||||
orm_mode = True
|
||||
|
||||
|
@ -140,6 +164,8 @@ class Recipe(RecipeSummary):
|
|||
|
||||
@validator("slug", always=True, pre=True)
|
||||
def validate_slug(slug: str, values):
|
||||
if not values["name"]:
|
||||
return slug
|
||||
name: str = values["name"]
|
||||
calc_slug: str = slugify(name)
|
||||
|
||||
|
|
|
@ -32,7 +32,7 @@ class ExportDatabase:
|
|||
export_tag = datetime.now().strftime("%Y-%b-%d")
|
||||
|
||||
self.main_dir = app_dirs.TEMP_DIR.joinpath(export_tag)
|
||||
self.img_dir = self.main_dir.joinpath("images")
|
||||
self.recipes = self.main_dir.joinpath("recipes")
|
||||
self.templates_dir = self.main_dir.joinpath("templates")
|
||||
|
||||
try:
|
||||
|
@ -43,7 +43,7 @@ class ExportDatabase:
|
|||
|
||||
required_dirs = [
|
||||
self.main_dir,
|
||||
self.img_dir,
|
||||
self.recipes,
|
||||
self.templates_dir,
|
||||
]
|
||||
|
||||
|
@ -67,10 +67,10 @@ class ExportDatabase:
|
|||
with open(out_file, "w") as f:
|
||||
f.write(content)
|
||||
|
||||
def export_images(self):
|
||||
shutil.copytree(app_dirs.IMG_DIR, self.img_dir, dirs_exist_ok=True)
|
||||
def export_recipe_dirs(self):
|
||||
shutil.copytree(app_dirs.RECIPE_DATA_DIR, self.recipes, dirs_exist_ok=True)
|
||||
|
||||
def export_items(self, items: list[BaseModel], folder_name: str, export_list=True):
|
||||
def export_items(self, items: list[BaseModel], folder_name: str, export_list=True, slug_folder=False):
|
||||
items = [x.dict() for x in items]
|
||||
out_dir = self.main_dir.joinpath(folder_name)
|
||||
out_dir.mkdir(parents=True, exist_ok=True)
|
||||
|
@ -79,8 +79,9 @@ class ExportDatabase:
|
|||
ExportDatabase._write_json_file(items, out_dir.joinpath(f"{folder_name}.json"))
|
||||
else:
|
||||
for item in items:
|
||||
filename = sanitize_filename(f"{item.get('name')}.json")
|
||||
ExportDatabase._write_json_file(item, out_dir.joinpath(filename))
|
||||
final_dest = out_dir if not slug_folder else out_dir.joinpath(item.get("slug"))
|
||||
filename = sanitize_filename(f"{item.get('slug')}.json")
|
||||
ExportDatabase._write_json_file(item, final_dest.joinpath(filename))
|
||||
|
||||
@staticmethod
|
||||
def _write_json_file(data: Union[dict, list], out_file: Path):
|
||||
|
@ -121,9 +122,9 @@ def backup_all(
|
|||
|
||||
if export_recipes:
|
||||
all_recipes = db.recipes.get_all(session)
|
||||
db_export.export_items(all_recipes, "recipes", export_list=False)
|
||||
db_export.export_recipe_dirs()
|
||||
db_export.export_items(all_recipes, "recipes", export_list=False, slug_folder=True)
|
||||
db_export.export_templates(all_recipes)
|
||||
db_export.export_images()
|
||||
|
||||
if export_settings:
|
||||
all_settings = db.settings.get_all(session)
|
||||
|
|
|
@ -2,7 +2,7 @@ import json
|
|||
import shutil
|
||||
import zipfile
|
||||
from pathlib import Path
|
||||
from typing import Callable, List
|
||||
from typing import Callable
|
||||
|
||||
from mealie.core.config import app_dirs
|
||||
from mealie.db.database import db
|
||||
|
@ -49,7 +49,7 @@ class ImportDatabase:
|
|||
def import_recipes(self):
|
||||
recipe_dir: Path = self.import_dir.joinpath("recipes")
|
||||
imports = []
|
||||
successful_imports = []
|
||||
successful_imports = {}
|
||||
|
||||
recipes = ImportDatabase.read_models_file(
|
||||
file_path=recipe_dir, model=Recipe, single_file=False, migrate=ImportDatabase._recipe_migration
|
||||
|
@ -68,7 +68,7 @@ class ImportDatabase:
|
|||
)
|
||||
|
||||
if import_status.status:
|
||||
successful_imports.append(recipe.slug)
|
||||
successful_imports.update({recipe.slug: recipe})
|
||||
|
||||
imports.append(import_status)
|
||||
|
||||
|
@ -105,15 +105,21 @@ class ImportDatabase:
|
|||
|
||||
return recipe_dict
|
||||
|
||||
def _import_images(self, successful_imports: List[str]):
|
||||
def _import_images(self, successful_imports: list[Recipe]):
|
||||
image_dir = self.import_dir.joinpath("images")
|
||||
for image in image_dir.iterdir():
|
||||
if image.stem in successful_imports:
|
||||
if image.is_dir():
|
||||
dest = app_dirs.IMG_DIR.joinpath(image.stem)
|
||||
shutil.copytree(image, dest, dirs_exist_ok=True)
|
||||
if image.is_file():
|
||||
shutil.copy(image, app_dirs.IMG_DIR)
|
||||
|
||||
if image_dir.exists():
|
||||
for image in image_dir.iterdir():
|
||||
item: Recipe = successful_imports.get(image.stem)
|
||||
|
||||
if item:
|
||||
dest_dir = item.image_dir
|
||||
|
||||
if image.is_dir():
|
||||
shutil.copytree(image, dest_dir, dirs_exist_ok=True)
|
||||
|
||||
if image.is_file():
|
||||
shutil.copy(image, dest_dir)
|
||||
|
||||
minify.migrate_images()
|
||||
|
||||
|
@ -227,7 +233,7 @@ class ImportDatabase:
|
|||
return [model(**g) for g in file_data]
|
||||
|
||||
all_models = []
|
||||
for file in file_path.glob("*.json"):
|
||||
for file in file_path.glob("**/*.json"):
|
||||
with open(file, "r") as f:
|
||||
file_data = json.loads(f.read())
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@ from pathlib import Path
|
|||
|
||||
import requests
|
||||
from mealie.core import root_logger
|
||||
from mealie.core.config import app_dirs
|
||||
from mealie.schema.recipe import Recipe
|
||||
from mealie.services.image import minify
|
||||
|
||||
logger = root_logger.get_logger()
|
||||
|
@ -20,47 +20,11 @@ class ImageOptions:
|
|||
IMG_OPTIONS = ImageOptions()
|
||||
|
||||
|
||||
def read_image(recipe_slug: str, image_type: str = "original") -> Path:
|
||||
"""returns the path to the image file for the recipe base of image_type
|
||||
|
||||
Args:
|
||||
recipe_slug (str): Recipe Slug
|
||||
image_type (str, optional): Glob Style Matcher "original*" | "min-original* | "tiny-original*"
|
||||
|
||||
Returns:
|
||||
Path: [description]
|
||||
"""
|
||||
recipe_slug = recipe_slug.split(".")[0] # Incase of File Name
|
||||
recipe_image_dir = app_dirs.IMG_DIR.joinpath(recipe_slug)
|
||||
|
||||
for file in recipe_image_dir.glob(image_type):
|
||||
return file
|
||||
|
||||
return None
|
||||
|
||||
|
||||
def rename_image(original_slug, new_slug) -> Path:
|
||||
current_path = app_dirs.IMG_DIR.joinpath(original_slug)
|
||||
new_path = app_dirs.IMG_DIR.joinpath(new_slug)
|
||||
|
||||
try:
|
||||
new_path = current_path.rename(new_path)
|
||||
except FileNotFoundError:
|
||||
logger.error(f"Image Directory {original_slug} Doesn't Exist")
|
||||
|
||||
return new_path
|
||||
|
||||
|
||||
def write_image(recipe_slug: str, file_data: bytes, extension: str) -> Path:
|
||||
try:
|
||||
delete_image(recipe_slug)
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
image_dir = Path(app_dirs.IMG_DIR.joinpath(f"{recipe_slug}"))
|
||||
image_dir.mkdir(exist_ok=True, parents=True)
|
||||
image_dir = Recipe(slug=recipe_slug).image_dir
|
||||
extension = extension.replace(".", "")
|
||||
image_path = image_dir.joinpath(f"original.{extension}")
|
||||
image_path.unlink(missing_ok=True)
|
||||
|
||||
if isinstance(file_data, Path):
|
||||
shutil.copy2(file_data, image_path)
|
||||
|
@ -77,12 +41,6 @@ def write_image(recipe_slug: str, file_data: bytes, extension: str) -> Path:
|
|||
return image_path
|
||||
|
||||
|
||||
def delete_image(recipe_slug: str) -> str:
|
||||
recipe_slug = recipe_slug.split(".")[0]
|
||||
for file in app_dirs.IMG_DIR.glob(f"{recipe_slug}*"):
|
||||
return shutil.rmtree(file)
|
||||
|
||||
|
||||
def scrape_image(image_url: str, slug: str) -> Path:
|
||||
if isinstance(image_url, str): # Handles String Types
|
||||
image_url = image_url
|
||||
|
@ -96,7 +54,7 @@ def scrape_image(image_url: str, slug: str) -> Path:
|
|||
image_url = image_url.get("url")
|
||||
|
||||
filename = slug + "." + image_url.split(".")[-1]
|
||||
filename = app_dirs.IMG_DIR.joinpath(filename)
|
||||
filename = Recipe(slug=slug).image_dir.joinpath(filename)
|
||||
|
||||
try:
|
||||
r = requests.get(image_url, stream=True)
|
||||
|
|
|
@ -4,10 +4,8 @@ from pathlib import Path
|
|||
|
||||
from mealie.core import root_logger
|
||||
from mealie.core.config import app_dirs
|
||||
from mealie.db.database import db
|
||||
from mealie.db.db_setup import create_session
|
||||
from mealie.schema.recipe import Recipe
|
||||
from PIL import Image
|
||||
from sqlalchemy.orm.session import Session
|
||||
|
||||
logger = root_logger.get_logger()
|
||||
|
||||
|
@ -20,11 +18,7 @@ class ImageSizes:
|
|||
|
||||
|
||||
def get_image_sizes(org_img: Path, min_img: Path, tiny_img: Path) -> ImageSizes:
|
||||
return ImageSizes(
|
||||
org=sizeof_fmt(org_img),
|
||||
min=sizeof_fmt(min_img),
|
||||
tiny=sizeof_fmt(tiny_img),
|
||||
)
|
||||
return ImageSizes(org=sizeof_fmt(org_img), min=sizeof_fmt(min_img), tiny=sizeof_fmt(tiny_img))
|
||||
|
||||
|
||||
def minify_image(image_file: Path) -> ImageSizes:
|
||||
|
@ -110,28 +104,9 @@ def move_all_images():
|
|||
if new_file.is_file():
|
||||
new_file.unlink()
|
||||
image_file.rename(new_file)
|
||||
|
||||
|
||||
def validate_slugs_in_database(session: Session = None):
|
||||
def check_image_path(image_name: str, slug_path: str) -> bool:
|
||||
existing_path: Path = app_dirs.IMG_DIR.joinpath(image_name)
|
||||
slug_path: Path = app_dirs.IMG_DIR.joinpath(slug_path)
|
||||
|
||||
if existing_path.is_dir():
|
||||
slug_path.rename(existing_path)
|
||||
else:
|
||||
logger.info("No Image Found")
|
||||
|
||||
session = session or create_session()
|
||||
all_recipes = db.recipes.get_all(session)
|
||||
|
||||
slugs_and_images = [(x.slug, x.image) for x in all_recipes]
|
||||
|
||||
for slug, image in slugs_and_images:
|
||||
image_slug = image.split(".")[0] # Remove Extension
|
||||
if slug != image_slug:
|
||||
logger.info(f"{slug}, Doesn't Match '{image_slug}'")
|
||||
check_image_path(image, slug)
|
||||
if image_file.is_dir():
|
||||
slug = image_file.name
|
||||
image_file.rename(Recipe(slug=slug).image_dir)
|
||||
|
||||
|
||||
def migrate_images():
|
||||
|
@ -139,7 +114,7 @@ def migrate_images():
|
|||
|
||||
move_all_images()
|
||||
|
||||
for image in app_dirs.IMG_DIR.glob("*/original.*"):
|
||||
for image in app_dirs.RECIPE_DATA_DIR.glob("**/original.*"):
|
||||
|
||||
minify_image(image)
|
||||
|
||||
|
@ -148,4 +123,3 @@ def migrate_images():
|
|||
|
||||
if __name__ == "__main__":
|
||||
migrate_images()
|
||||
validate_slugs_in_database()
|
||||
|
|
0
mealie/services/recipe/__init__.py
Normal file
0
mealie/services/recipe/__init__.py
Normal file
22
mealie/services/recipe/asset.py
Normal file
22
mealie/services/recipe/asset.py
Normal file
|
@ -0,0 +1,22 @@
|
|||
from pathlib import Path
|
||||
|
||||
from mealie.core.config import app_dirs
|
||||
from mealie.core.root_logger import get_logger
|
||||
from mealie.schema.recipe import Recipe
|
||||
|
||||
logger = get_logger()
|
||||
|
||||
|
||||
def check_asset(original_slug, recipe: Recipe) -> Path:
|
||||
if original_slug == recipe.slug:
|
||||
return recipe.assets
|
||||
|
||||
current_dir = app_dirs.RECIPE_DATA_DIR.joinpath(original_slug)
|
||||
|
||||
try:
|
||||
current_dir.rename(recipe.directory)
|
||||
except FileNotFoundError:
|
||||
logger.error(f"Recipe Directory not Found: {original_slug}")
|
||||
logger.info(f"Renaming Recipe Directory: {original_slug} -> {recipe.slug}")
|
||||
|
||||
return current_dir.absolute()
|
Loading…
Add table
Add a link
Reference in a new issue