feat: duplicate detection + original URL in description
- Add original recipe URL to Mealie description (appended after blank line) - Check for duplicate recipes on scrape (match orgURL or URL in description) - Show warning with link to existing recipe if duplicate found - User can still import anyway (warning only, not blocking) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
+41
-2
@@ -29,6 +29,40 @@ class MealieClient:
|
||||
r.raise_for_status()
|
||||
return r.json()
|
||||
|
||||
def find_duplicate(self, url: str, title: str = "") -> dict | None:
|
||||
"""Check if a recipe with this original URL already exists.
|
||||
|
||||
Searches by URL in orgURL and description fields.
|
||||
Returns {"slug": ..., "name": ..., "url": ...} or None.
|
||||
"""
|
||||
if not url:
|
||||
return None
|
||||
# Search by title to find candidates (Mealie search matches name)
|
||||
search_term = title or url.split("/")[-1].replace("-", " ")
|
||||
r = self.session.get(
|
||||
f"{self.api_url}/api/recipes",
|
||||
params={"search": search_term, "perPage": 50},
|
||||
timeout=10,
|
||||
)
|
||||
if not r.ok:
|
||||
return None
|
||||
for item in r.json().get("items", []):
|
||||
detail = self.session.get(
|
||||
f"{self.api_url}/api/recipes/{item['slug']}", timeout=10
|
||||
)
|
||||
if not detail.ok:
|
||||
continue
|
||||
data = detail.json()
|
||||
org = data.get("orgURL", "") or ""
|
||||
desc = data.get("description", "") or ""
|
||||
if org == url or url in desc:
|
||||
return {
|
||||
"slug": data["slug"],
|
||||
"name": data.get("name", data["slug"]),
|
||||
"url": f"{self.base_url}/g/home/r/{data['slug']}",
|
||||
}
|
||||
return None
|
||||
|
||||
def create_recipe(self, recipe: dict) -> str:
|
||||
"""Create a recipe in Mealie from a scraper result dict.
|
||||
|
||||
@@ -175,12 +209,17 @@ class MealieClient:
|
||||
"ingredientReferences": [],
|
||||
})
|
||||
|
||||
description = recipe.get("description", "")
|
||||
original_url = recipe.get("original_url", "")
|
||||
if original_url and original_url not in description:
|
||||
description = f"{description}\n\n{original_url}".strip()
|
||||
|
||||
return {
|
||||
"name": recipe["title"],
|
||||
"description": recipe.get("description", ""),
|
||||
"description": description,
|
||||
"recipeIngredient": ingredients,
|
||||
"recipeInstructions": instructions,
|
||||
"orgURL": recipe.get("original_url", ""),
|
||||
"orgURL": original_url,
|
||||
"recipeYield": "",
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user