{ "name": "Email Scheduled Recipe Suggestions", "nodes": [ { "name": "Cron", "type": "n8n-nodes-base.cron", "position": [ 100, 400 ], "parameters": { "triggerTimes": { "item": [ { "hour": 10 } ] } }, "typeVersion": 1, "id": "email-scheduled-recipe-suggestions-0" }, { "name": "Prepare recipe search", "type": "n8n-nodes-base.code", "typeVersion": 2, "parameters": { "mode": "runOnceForEachItem", "jsCode": "function recipeQuery({query,diet,minCalories,maxCalories,minMinutes,maxMinutes,maxIngredients,health,count}) {\n if(typeof query!=='string'||!query.trim()||/[\\r\\n]/.test(query)||query.startsWith('YOUR_'))throw Error('Configure a recipe search term');\n const diets=['balanced','high-fiber','high-protein','low-carb','low-fat','low-sodium'];if(diet==='random')diet=diets[Math.floor(Math.random()*diets.length)];if(!diets.includes(diet))throw Error('Choose a supported diet filter');\n const allowed=['alcohol-free','celery-free','crustacean-free','dairy-free','egg-free','fish-free','fodmap-free','gluten-free','keto-friendly','kidney-friendly','kosher','low-fat-abs','low-potassium','low-sugar','lupine-free','mustard-free','no-oil-added','paleo','peanut-free','pescatarian','pork-free','red-meat-free','sesame-free','shellfish-free','soy-free','sugar-conscious','tree-nut-free','vegan','vegetarian','wheat-free'];\n if(health==='random')health=allowed[Math.floor(Math.random()*allowed.length)];if(!allowed.includes(health))throw Error('Choose a supported health filter');\n for(const n of [minCalories,minMinutes])if(!Number.isSafeInteger(n)||n<0)throw Error('Set nonnegative search minimums');for(const n of [maxCalories,maxMinutes,maxIngredients,count])if(!Number.isSafeInteger(n)||n<1)throw Error('Set positive integer search limits');if(minCalories>maxCalories||minMinutes>maxMinutes||count>20)throw Error('Invalid search range or recipe count');\n const p={type:'public',q:query.trim(),diet,health,calories:`${minCalories}-${maxCalories}`,time:`${minMinutes}-${maxMinutes}`,ingr:String(maxIngredients),random:'true'};return {url:'https://api.edamam.com/api/recipes/v2?'+Object.entries(p).map(([k,v])=>encodeURIComponent(k)+'='+encodeURIComponent(v)).join('&'),query:query.trim(),diet,health,maxCalories,maxMinutes,count};\n}\n\nreturn {json:recipeQuery({query:'chicken',diet:'balanced',health:'random',minCalories:0,maxCalories:1500,minMinutes:0,maxMinutes:30,maxIngredients:5,count:3})};" }, "id": "email-scheduled-recipe-suggestions-1" }, { "name": "Find random recipes", "type": "n8n-nodes-base.httpRequest", "typeVersion": 4.2, "parameters": { "url": "={{ $json.url }}", "authentication": "genericCredentialType", "genericAuthType": "httpBasicAuth", "options": {} }, "id": "email-scheduled-recipe-suggestions-2" }, { "name": "Format recipe links", "type": "n8n-nodes-base.code", "typeVersion": 2, "parameters": { "mode": "runOnceForEachItem", "jsCode": "function recipeFormat({body,query,diet,health,maxCalories,maxMinutes,count}) {\n if(!body||!Array.isArray(body.hits))throw Error('Invalid recipe response');if(!body.hits.length)throw Error('No recipes matched the selected filters');\n const escape=s=>String(s).replace(/&/g,'&').replace(//g,'>').replace(/\"/g,'"').replace(/'/g,''');\n const validUrl=u=>{if(typeof u!=='string'||/[\\s\\x00-\\x1f\\x7f\\\\]/.test(u)||/%(?![0-9a-f]{2})/i.test(u))return false;const m=/^https:\\/\\/([^/?#]+)(?:[/?#].*)?$/i.exec(u);if(!m||m[1].length>253)return false;const labels=m[1].replace(/\\.$/,'').split('.');if(!labels.every(x=>x.length>0&&x.length<=63&&/^[a-z0-9](?:[a-z0-9-]*[a-z0-9])?$/i.test(x)))return false;if(labels.every(x=>/^\\d+$/.test(x))&&(labels.length!==4||labels.some(x=>Number(x)>255)))return false;return true};\n const links=body.hits.slice(0,count).map(({recipe})=>{const u=recipe?.shareAs,name=recipe?.label;if(typeof name!=='string'||!name.trim()||!validUrl(u))throw Error('Invalid recipe link or label');return `