feat(recipes): add recipe categories support (v0.8.0)

- New tool: get_recipe_categories() lists available recipe category IDs
- Enhanced create_recipe and update_recipe with optional category_ids parameter
- Extended get_recipe and get_recipes to include category_ids in response
- Updated parse_recipe_full() to extract recipeCategoryIdList from API response
- Extended build_create_params() and build_update_params() to handle category_ids

Recipe categories are managed via recipe.recipeCategoryIdList in mprecipeput API.
Categories are represented as a list of category IDs (e.g. ["category/23431854_2"]).
No direct API endpoint exists for listing all categories; they are discovered from
existing recipes or must be known in advance.

Version: 0.7.5 → 0.8.0
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
This commit is contained in:
2026-04-17 06:24:48 +02:00
parent eb022e2376
commit 4c60b5b5fa
7 changed files with 123 additions and 16 deletions
+24 -4
View File
@@ -75,6 +75,15 @@ def parse_recipe_full(raw: dict[str, Any]) -> dict[str, Any]:
ingredients_list_raw: list[dict[str, Any]] = raw.get("ingredientsList") or []
ingredients_parsed = [item.get("name") for item in ingredients_list_raw if item.get("name")]
# Extract recipe categories from API response.
# The API provides both recipeCategoryIdList (actual IDs) and recipeCategories
# (system name strings). We use the ID list as the authoritative source.
categories: list[str] = []
category_ids: list[str] = raw.get("recipeCategoryIdList") or []
for cat_id in category_ids:
if cat_id:
categories.append(cat_id)
return {
"id": raw.get("metaId"),
"name": raw.get("name"),
@@ -91,6 +100,7 @@ def parse_recipe_full(raw: dict[str, Any]) -> dict[str, Any]:
"can_update": raw.get("rights", {}).get("canUpdate") == "true",
"created_at": raw.get("creationDate"),
"account_id": raw.get("accountId"),
"category_ids": categories,
}
@@ -103,7 +113,8 @@ def build_create_params(
cook_time_minutes: int | None = None,
serves: int | None = None,
url: str | None = None,
) -> dict[str, str]:
category_ids: list[str] | None = None,
) -> dict[str, str | list[str]]:
"""Build the form parameters for a mprecipeput create call.
The Family Wall API requires the 'recipe.' prefix for all recipe fields.
@@ -124,11 +135,13 @@ def build_create_params(
cook_time_minutes: Optional cooking time in minutes.
serves: Optional number of servings.
url: Optional external URL (e.g. original recipe source).
category_ids: Optional list of recipe category IDs
(e.g. ``["category/23431854_2"]``).
Returns:
Dict of form parameters ready to send to mprecipeput.
"""
params: dict[str, str] = {
params: dict[str, str | list[str]] = {
"recipe.name": name,
"recipe.isRecipe": "true",
}
@@ -146,6 +159,8 @@ def build_create_params(
params["recipe.serves"] = str(serves)
if url is not None:
params["recipe.url"] = url
if category_ids is not None:
params["recipe.recipeCategoryIdList"] = category_ids
return params
@@ -160,7 +175,8 @@ def build_update_params(
cook_time_minutes: int | None = None,
serves: int | None = None,
url: str | None = None,
) -> dict[str, str]:
category_ids: list[str] | None = None,
) -> dict[str, str | list[str]]:
"""Build the form parameters for a mprecipeput update call.
Identical to :func:`build_create_params` except that ``recipe.metaId`` is
@@ -183,11 +199,13 @@ def build_update_params(
cook_time_minutes: New cooking time in minutes (omit to keep existing).
serves: New number of servings (omit to keep existing).
url: New external URL (omit to keep existing).
category_ids: New list of recipe category IDs (omit to keep existing).
Pass empty list to remove all categories.
Returns:
Dict of form parameters ready to send to mprecipeput.
"""
params: dict[str, str] = {
params: dict[str, str | list[str]] = {
"recipe.metaId": recipe_id,
"recipe.name": name if name is not None else current_name,
"recipe.isRecipe": "true",
@@ -206,4 +224,6 @@ def build_update_params(
params["recipe.serves"] = str(serves)
if url is not None:
params["recipe.url"] = url
if category_ids is not None:
params["recipe.recipeCategoryIdList"] = category_ids
return params