4.2 KiB
KitchenOwl Recipe Import (Doris-managed)
Why this exists
KitchenOwl's built-in import/scrape flow is unreliable for the way John and Leanne actually send recipe links around.
This repo-side helper gives Doris a safer path:
- try KitchenOwl's native
/recipe/scrapeendpoint for sites it understands - if that fails, fetch the page directly
- extract schema.org
RecipeJSON-LD - normalize ingredients/tags/timings into KitchenOwl's create-recipe payload
- optionally create the recipe through the KitchenOwl API
That means Doris can ingest recipe links from chat without depending on KitchenOwl's flaky native importer.
Script
automation/bin/kitchenowl_recipe_import.py
Default mode is dry-run. It prints the normalized KitchenOwl payload and does not create anything unless --create is passed.
Required env vars
Put these in a live .env file or export them ad hoc. Do not commit live secrets.
KITCHENOWL_BASE_URL=https://owl.paccoco.com
KITCHENOWL_API_TOKEN=CHANGE_ME
KITCHENOWL_HOUSEHOLD_ID=1
Notes:
KITCHENOWL_API_TOKENshould be a long-lived token for a user who can create recipes in the target household.KITCHENOWL_HOUSEHOLD_IDfor the current live instance is1(Stafford's) unless that changes later.
Usage
Dry-run a link
cd /home/fizzlepoof/repos/truenas-stacks
export KITCHENOWL_BASE_URL=https://owl.paccoco.com
export KITCHENOWL_API_TOKEN=...redacted...
export KITCHENOWL_HOUSEHOLD_ID=1
automation/bin/kitchenowl_recipe_import.py --pretty \
"https://example.com/my-recipe"
Actually create the recipe
automation/bin/kitchenowl_recipe_import.py --pretty --create \
"https://example.com/my-recipe"
Import several links at once
automation/bin/kitchenowl_recipe_import.py --create --pretty \
"https://example.com/recipe-1" \
"https://example.com/recipe-2"
Behavior details
Strategy order
By default the helper tries:
GET /api/household/<id>/recipe/scrape?url=...- if KitchenOwl returns
Unsupported websiteor otherwise fails, Doris falls back to direct HTML fetch + JSON-LD parse
If you want to skip the built-in scrape and go straight to Doris mode:
automation/bin/kitchenowl_recipe_import.py --skip-kitchenowl-scrape --pretty URL
Duplicate protection
Before creating a recipe, the helper loads existing household recipes and skips creation if it finds:
- an exact matching
sourceURL, or - an exact matching recipe
name
To force duplicates anyway:
automation/bin/kitchenowl_recipe_import.py --create --allow-duplicates URL
Visibility
KitchenOwl visibility enum:
0= private (default)1= link2= public
Example:
automation/bin/kitchenowl_recipe_import.py --create --visibility 0 URL
What parses well
The fallback parser works best on recipe pages that expose proper schema.org Recipe JSON-LD, which many decent recipe sites do.
It pulls:
- name
- description
- instructions
- ingredient list
- total/prep/cook time
- yield/servings
- categories/cuisine/keywords → KitchenOwl tags
Known limitations
- Some sites block scraping aggressively; Doris first tries normal fetch, then falls back to
curlheaders for better odds. - Ingredient normalization is heuristic, not magic. It aims for a sane KitchenOwl item name plus a description/amount, but some weird ingredients may still need manual cleanup.
- Recipe source images are now forwarded into KitchenOwl when the source exposes a usable image URL.
- The helper expects structured JSON-LD. If a site hides the recipe entirely in client-side blobs or anti-bot nonsense, manual copy/paste may still be needed.
GET /api/settingson the live KitchenOwl instance currently returns500, but that does not block recipe import.
Doris workflow expectation
Preferred operator flow when John or Leanne sends recipe links:
- Doris runs a dry-run first when the site is unfamiliar or suspicious.
- If the normalized payload looks sane, Doris reruns with
--create. - If the page is too messy, Doris asks for the raw ingredients/steps and imports it manually.
That keeps KitchenOwl as the recipe store while making Doris the reliable intake layer.