Files
n8n/backups/2025-12-27/tg_callbacks.json
2025-12-27 21:49:48 +00:00

1 line
39 KiB
JSON
Raw Permalink Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
{"updatedAt":"2025-11-30T14:49:06.937Z","createdAt":"2025-11-30T14:22:03.470Z","id":"jZIoYr8RW41K0j4J","name":"tg_callbacks","active":false,"isArchived":false,"nodes":[{"parameters":{"content":"# нажал ДА = ВЫБЕРИ ВЕС","height":292,"width":1178,"color":4},"id":"8cbb64b7-c351-4b48-8870-6c6ec65498c7","name":"Sticky Note5","type":"n8n-nodes-base.stickyNote","position":[0,448],"typeVersion":1},{"parameters":{"updates":["*"],"additionalFields":{}},"type":"n8n-nodes-base.telegramTrigger","typeVersion":1.2,"position":[-624,1152],"id":"de564fd6-34c6-4a15-acbb-416dcb225a40","name":"Telegram Trigger","webhookId":"e4d6b058-dc8c-4130-9abd-41243518e824","credentials":{"telegramApi":{"id":"R8VDF53JH3mzhoHd","name":"Telegram dieta"}}},{"parameters":{"rules":{"values":[{"conditions":{"options":{"caseSensitive":true,"leftValue":"","typeValidation":"strict","version":2},"conditions":[{"id":"52493568-0b68-46b8-b18a-894cf77bcac1","leftValue":"={{$json.callback_query.data}}","rightValue":"manual_","operator":{"type":"string","operation":"startsWith"}}],"combinator":"and"},"renameOutput":true,"outputKey":"manual"},{"conditions":{"options":{"caseSensitive":true,"leftValue":"","typeValidation":"strict","version":2},"conditions":[{"id":"5eeb9b3f-d4ce-45f6-bb62-32244fd9a99a","leftValue":"={{ $json.message.photo[0] }}","rightValue":"","operator":{"type":"object","operation":"exists","singleValue":true}}],"combinator":"and"},"renameOutput":true,"outputKey":"image"},{"conditions":{"options":{"caseSensitive":true,"leftValue":"","typeValidation":"strict","version":2},"conditions":[{"id":"2f1495ad-2eb2-4729-af5a-23c949adce8c","leftValue":"={{$json.callback_query.data}}","rightValue":"dish_yes_","operator":{"type":"string","operation":"startsWith"}}],"combinator":"and"},"renameOutput":true,"outputKey":"dish_yes"},{"conditions":{"options":{"caseSensitive":true,"leftValue":"","typeValidation":"strict","version":2},"conditions":[{"leftValue":"={{$json.callback_query.data}}","rightValue":"dish_no_","operator":{"type":"string","operation":"startsWith"},"id":"c9ead52e-1b81-453a-bd9b-1d18dcbd82bb"}],"combinator":"and"},"renameOutput":true,"outputKey":"dish_no"},{"conditions":{"options":{"caseSensitive":true,"leftValue":"","typeValidation":"strict","version":2},"conditions":[{"id":"646db5d3-3518-4edf-9374-cef371fa7ba9","leftValue":"={{$json.callback_query.data}}","rightValue":"alt_","operator":{"type":"string","operation":"startsWith"}}],"combinator":"and"},"renameOutput":true,"outputKey":"alt"},{"conditions":{"options":{"caseSensitive":true,"leftValue":"","typeValidation":"strict","version":2},"conditions":[{"id":"1bcf1e75-3e73-465b-8bbb-2665b845e7e9","leftValue":"={{$json.callback_query.data}}","rightValue":"weight_","operator":{"type":"string","operation":"startsWith"}}],"combinator":"and"},"renameOutput":true,"outputKey":"weight"},{"conditions":{"options":{"caseSensitive":true,"leftValue":"","typeValidation":"strict","version":2},"conditions":[{"id":"90573faf-164a-418f-a4a8-b69d3e7aaf3d","leftValue":"={{$json.callback_query.data}}","rightValue":"cancel_","operator":{"type":"string","operation":"startsWith"}}],"combinator":"and"},"renameOutput":true,"outputKey":"cancel"},{"conditions":{"options":{"caseSensitive":true,"leftValue":"","typeValidation":"strict","version":2},"conditions":[{"id":"6166763a-38e9-494a-aea0-20bdc9626314","leftValue":"={{ $json.message.text }}","rightValue":"/","operator":{"type":"string","operation":"exists","singleValue":true}}],"combinator":"and"},"renameOutput":true,"outputKey":"text_cmd"}]},"options":{}},"type":"n8n-nodes-base.switch","typeVersion":3.2,"position":[-416,1040],"id":"77416214-f1c4-4160-ae59-2c266ceec40b","name":"Switch"},{"parameters":{"jsCode":"// alt_0_7 → parts = ['alt','0','7']\nconst [, idx, id] = $json.callback_query.data.split('_');\n\nreturn [{\n json: {\n chat_id : $json.callback_query.message.chat.id, // ID чата, где лежит сообщение-клавиатура\n draft_id : Number(id), // 7\n alt_idx : Number(idx), // 0 / 1 / 2\n del_msg_id : $json.callback_query.message.message_id // ID сообщения, которое надо удалить\n }\n}];\n"},"type":"n8n-nodes-base.code","typeVersion":2,"position":[64,1168],"id":"f0f7a047-5dd6-47e0-b420-22f1d2d4b244","name":"Parse alt"},{"parameters":{"operation":"get","tableId":"meals_draft","filters":{"conditions":[{"keyName":"chat_id","keyValue":"={{$json.chat_id}}"},{"keyName":"message_id","keyValue":"={{$json.draft_id}}"},{"keyName":"status","keyValue":"await_alt"}]}},"type":"n8n-nodes-base.supabase","typeVersion":1,"position":[448,1168],"id":"dc33c3e0-b25b-415d-bef5-8fd1eb637e90","name":"GET 3","credentials":{"supabaseApi":{"id":"OoOx3pPUNd1lRJTr","name":"Supabase account"}}},{"parameters":{"operation":"update","tableId":"meals_draft","filters":{"conditions":[{"keyName":"chat_id","condition":"eq","keyValue":"={{ $json.chat_id }}"},{"keyName":"message_id","condition":"eq","keyValue":"={{$json.draft_id}}"}]},"fieldsUi":{"fieldValues":[{"fieldId":"chosen_name","fieldValue":"={{$json.dish_ru}}"},{"fieldId":"grams_pred","fieldValue":"={{$json.grams_est}}"},{"fieldId":"status","fieldValue":"await_weight"},{"fieldId":"updated_at","fieldValue":"={{ new Date().toISOString() }}"}]}},"type":"n8n-nodes-base.supabase","typeVersion":1,"position":[768,1184],"id":"f2b7c43e-769e-414d-b91b-7d9b010278bb","name":"UPDATE 3","credentials":{"supabaseApi":{"id":"OoOx3pPUNd1lRJTr","name":"Supabase account"}}},{"parameters":{"content":"# нажал НЕТ + ЕЩЕ 2 варианта","height":292,"width":1178,"color":3},"id":"4f107a54-cfa4-468d-a5d8-26f381e91e82","name":"Sticky Note","type":"n8n-nodes-base.stickyNote","position":[0,768],"typeVersion":1},{"parameters":{"content":"# нажал на 1/2 = ВЫБЕРИ ВЕС","height":292,"width":1178,"color":3},"id":"54fcc08b-bf5c-4e18-b972-8327f858ddf7","name":"Sticky Note1","type":"n8n-nodes-base.stickyNote","position":[0,1088],"typeVersion":1},{"parameters":{"content":"# РЕЗУЛЬТАТ\n\n","height":392,"width":1758,"color":4},"id":"8fb8dda2-b400-40e0-81bd-fdedfd69df23","name":"Sticky Note2","type":"n8n-nodes-base.stickyNote","position":[0,1408],"typeVersion":1},{"parameters":{"operation":"update","tableId":"meals_draft","filters":{"conditions":[{"keyName":"chat_id","condition":"eq","keyValue":"={{ $json.chat_id }}"},{"keyName":"message_id","condition":"eq","keyValue":"={{$json.draft_id}}"}]},"fieldsUi":{"fieldValues":[{"fieldId":"grams_pred","fieldValue":"={{$json.grams}}"},{"fieldId":"status","fieldValue":"done"},{"fieldId":"updated_at","fieldValue":"={{ new Date().toISOString() }}"}]}},"type":"n8n-nodes-base.supabase","typeVersion":1,"position":[1392,1632],"id":"981f62eb-7550-4756-825f-1377dffc59fd","name":"UPDATE 4","credentials":{"supabaseApi":{"id":"OoOx3pPUNd1lRJTr","name":"Supabase account"}}},{"parameters":{"chatId":"={{$json.chat_id}}","text":"=*{{ $json.dish }} {{ $json.grams }} г*\n\n*Калорий:* {{ $json.kcal }}\n*Б:* {{ $json.prot }}*Ж:* {{ $json.fat }}*У:* {{ $json.carb }}\n\n✔ _сохранил в память_","replyMarkup":"inlineKeyboard","inlineKeyboard":{"rows":[{"row":{"buttons":[{"text":"🚫 не сохранять","additionalFields":{"callback_data":"=cancel_{{ $json.id }}"}}]}}]},"additionalFields":{"appendAttribution":false,"parse_mode":"Markdown"}},"type":"n8n-nodes-base.telegram","typeVersion":1.2,"position":[1568,1440],"id":"d9c2dc63-f07a-4732-8c43-a8e2ea1881e6","name":"DONE","webhookId":"54ba5fcc-0866-4f93-aa38-bad03e1710e6","credentials":{"telegramApi":{"id":"R8VDF53JH3mzhoHd","name":"Telegram dieta"}}},{"parameters":{"operation":"get","tableId":"meals_draft","filters":{"conditions":[{"keyName":"chat_id","keyValue":"={{$json.chat_id}}"},{"keyName":"message_id","keyValue":"={{$json.draft_id}}"},{"keyName":"status","keyValue":"await_dish"}]}},"type":"n8n-nodes-base.supabase","typeVersion":1,"position":[448,848],"id":"e382162d-8c34-4836-b159-6c68964d94f9","name":"GET 2","credentials":{"supabaseApi":{"id":"OoOx3pPUNd1lRJTr","name":"Supabase account"}}},{"parameters":{"operation":"update","tableId":"meals_draft","filters":{"conditions":[{"keyName":"chat_id","condition":"eq","keyValue":"={{ $json.chat_id }}"},{"keyName":"message_id","condition":"eq","keyValue":"={{$json.draft_id}}"}]},"fieldsUi":{"fieldValues":[{"fieldId":"status","fieldValue":"await_alt"},{"fieldId":"updated_at","fieldValue":"={{ new Date().toISOString() }}"}]}},"type":"n8n-nodes-base.supabase","typeVersion":1,"position":[768,864],"id":"db2269cb-082a-46d0-98d2-a4dc82618059","name":"UPDATE 2","credentials":{"supabaseApi":{"id":"OoOx3pPUNd1lRJTr","name":"Supabase account"}}},{"parameters":{"operation":"update","tableId":"meals_draft","filters":{"conditions":[{"keyName":"chat_id","condition":"eq","keyValue":"={{ $json.chat_id }}"},{"keyName":"message_id","condition":"eq","keyValue":"={{$json.draft_id}}"}]},"fieldsUi":{"fieldValues":[{"fieldId":"chosen_name","fieldValue":"={{$json.dish_ru}}"},{"fieldId":"status","fieldValue":"await_weight"},{"fieldId":"updated_at","fieldValue":"={{ new Date().toISOString() }}"}]}},"type":"n8n-nodes-base.supabase","typeVersion":1,"position":[768,544],"id":"e07d29c3-4443-432b-a571-1ce443b5833e","name":"UPDATE 1","credentials":{"supabaseApi":{"id":"OoOx3pPUNd1lRJTr","name":"Supabase account"}}},{"parameters":{"operation":"get","tableId":"meals_draft","filters":{"conditions":[{"keyName":"chat_id","keyValue":"={{$json.chat_id}}"},{"keyName":"message_id","keyValue":"={{$json.draft_id}}"},{"keyName":"status","keyValue":"await_dish"}]}},"type":"n8n-nodes-base.supabase","typeVersion":1,"position":[448,528],"id":"e0a044e2-5370-4ceb-8150-23efbbd287b2","name":"GET 1","credentials":{"supabaseApi":{"id":"OoOx3pPUNd1lRJTr","name":"Supabase account"}}},{"parameters":{"chatId":"={{$json.chat_id}}","text":"Выбери массу порции:","replyMarkup":"inlineKeyboard","inlineKeyboard":{"rows":[{"row":{"buttons":[{"text":"={{$json.buttons[0].text}}","additionalFields":{"callback_data":"={{$json.buttons[0].data}}"}},{"text":"={{$json.buttons[1].text}}","additionalFields":{"callback_data":"={{$json.buttons[1].data}}"}},{"text":"={{$json.buttons[2].text}}","additionalFields":{"callback_data":"={{$json.buttons[2].data}}"}}]}}]},"additionalFields":{"appendAttribution":false}},"type":"n8n-nodes-base.telegram","typeVersion":1.2,"position":[960,1168],"id":"13871358-51f9-4b3c-8b20-70b65c18eb90","name":"await_weight 3","webhookId":"d3d32e66-ff1c-42d9-9bfe-cf7f223f745b","credentials":{"telegramApi":{"id":"R8VDF53JH3mzhoHd","name":"Telegram dieta"}}},{"parameters":{"chatId":"={{ $json.chat_id }}","text":"Выбери массу порции:","replyMarkup":"inlineKeyboard","inlineKeyboard":{"rows":[{"row":{"buttons":[{"text":"={{ $json.buttons[0].text }}","additionalFields":{"callback_data":"={{ $json.buttons[0].data }}"}},{"text":"={{ $json.buttons[1].text }}","additionalFields":{"callback_data":"={{ $json.buttons[1].data }}"}},{"text":"={{ $json.buttons[2].text }}","additionalFields":{"callback_data":"={{ $json.buttons[2].data }}"}}]}}]},"additionalFields":{"appendAttribution":false}},"type":"n8n-nodes-base.telegram","typeVersion":1.2,"position":[960,528],"id":"f0d2d066-1898-428e-9ab0-1239f76d256f","name":"await_weight 1","webhookId":"d3d32e66-ff1c-42d9-9bfe-cf7f223f745b","credentials":{"telegramApi":{"id":"R8VDF53JH3mzhoHd","name":"Telegram dieta"}}},{"parameters":{"chatId":"={{$json.chat_id}}","text":"=*Выберите альтернативу:*\n\n{{ $json.alt_lines.join('\\n') }}\n","replyMarkup":"inlineKeyboard","inlineKeyboard":{"rows":[{"row":{"buttons":[{"text":"={{$json.buttons[0].text}}","additionalFields":{"callback_data":"={{$json.buttons[0].data}}"}},{"text":"={{$json.buttons[1].text}}","additionalFields":{"callback_data":"={{$json.buttons[1].data}}"}}]}}]},"additionalFields":{"appendAttribution":false}},"type":"n8n-nodes-base.telegram","typeVersion":1.2,"position":[960,848],"id":"d2c24a86-a3fa-4432-a543-6c63fc00e436","name":"await_alt","webhookId":"d3d32e66-ff1c-42d9-9bfe-cf7f223f745b","credentials":{"telegramApi":{"id":"R8VDF53JH3mzhoHd","name":"Telegram dieta"}}},{"parameters":{"jsCode":"// weight_200_7 → parts = ['weight','200','7']\nconst [, grams, id] = $json.callback_query.data.split('_');\n\nreturn [{\n json: {\n chat_id : $json.callback_query.message.chat.id, // тот же chat_id\n draft_id : Number(id), // 7\n grams : Number(grams), // 200\n del_msg_id : $json.callback_query.message.message_id // ID клавиатуры веса\n }\n}];"},"type":"n8n-nodes-base.code","typeVersion":2,"position":[80,1504],"id":"28511818-7857-4075-a662-5a6647f128fe","name":"Split weight"},{"parameters":{"operation":"deleteMessage","chatId":"={{ $json.chat_id }}","messageId":"={{ $json.del_msg_id }}"},"type":"n8n-nodes-base.telegram","typeVersion":1.2,"position":[272,1632],"id":"b7d233d5-543a-440c-97a2-92b22ac7c717","name":"DEL await_weight","webhookId":"182771d4-324c-4a5e-9b6b-cb35d00a0a98","credentials":{"telegramApi":{"id":"R8VDF53JH3mzhoHd","name":"Telegram dieta"}}},{"parameters":{"operation":"deleteMessage","chatId":"={{ $json.chat_id }}","messageId":"={{ $json.del_msg_id }}"},"type":"n8n-nodes-base.telegram","typeVersion":1.2,"position":[240,1184],"id":"c9f1aab0-b659-49fb-b2c6-f67f83056aa4","name":"DEL await_alt","webhookId":"182771d4-324c-4a5e-9b6b-cb35d00a0a98","credentials":{"telegramApi":{"id":"R8VDF53JH3mzhoHd","name":"Telegram dieta"}}},{"parameters":{"operation":"deleteMessage","chatId":"={{ $json.chat_id }}","messageId":"={{ $json.del_msg_id }}"},"type":"n8n-nodes-base.telegram","typeVersion":1.2,"position":[240,864],"id":"7d79b792-e168-4721-ab67-d13b0af7d62f","name":"DEL dish_no","webhookId":"182771d4-324c-4a5e-9b6b-cb35d00a0a98","credentials":{"telegramApi":{"id":"R8VDF53JH3mzhoHd","name":"Telegram dieta"}}},{"parameters":{"operation":"deleteMessage","chatId":"={{ $json.chat_id }}","messageId":"={{ $json.del_msg_id }}"},"type":"n8n-nodes-base.telegram","typeVersion":1.2,"position":[240,544],"id":"2b82adaa-309e-420d-a480-5538fe31fae5","name":"DEL dish_yes","webhookId":"182771d4-324c-4a5e-9b6b-cb35d00a0a98","credentials":{"telegramApi":{"id":"R8VDF53JH3mzhoHd","name":"Telegram dieta"}}},{"parameters":{"jsCode":"/**\n * INPUT ожидает:\n * • items[0].json — строка-row из Supabase (`draft`)\n * • $json.alt_idx — 0 / 1 / 2 (пришло из «alt_0_<id>»)\n *\n * Правка: alt_idx указывает на элемент candidates[1…3],\n * поэтому делаем сдвиг +1.\n */\n\n// 0. Достаём draft: бывает либо объектом, либо массивом с одним элементом\nconst draft = Array.isArray(items[0].json)\n ? items[0].json[0]\n : items[0].json;\n\n// 1. candidates: если это строка — парсим\nconst candidates = typeof draft.candidates === 'string'\n ? JSON.parse(draft.candidates)\n : draft.candidates || [];\n\n// 2. выбираем нужную альтернативу (alt_idx + 1)\nconst offs = ($json.alt_idx ?? 0) + 1;\nconst cand = candidates[offs] || {\n dish : '(не найдено)',\n grams : draft.grams_pred || 200,\n};\n\n// 3. считаем три варианта массы\nconst g = Number(cand.grams) || 200;\nconst step = g < 120 ? 20 : 50;\nconst btns = [g - step, g, g + step].filter(x => x > 0);\n\nreturn [{\n json: {\n chat_id : draft.chat_id,\n draft_id : draft.message_id, // пригодится для UPDATE\n dish_ru : cand.dish,\n grams_est : g,\n buttons : btns.map(x => ({\n text : `${x} г`,\n data : `weight_${x}_${draft.message_id}`,\n })),\n },\n}];\n"},"type":"n8n-nodes-base.code","typeVersion":2,"position":[592,1168],"id":"3fa5e0f5-cfa6-4846-81a7-059879525667","name":"WEIGHT 3"},{"parameters":{"jsCode":"/** INPUT ожидает:\n * • items[0].json ← строка из Supabase (`draft`)\n * • $json.alt_idx ← 0 / 1 / 2 (пришло из «alt_0_id»)\n */\n\n/* 0. draft может лежать либо прямо в .json, либо в .json[0]\n (зависит от Always Output Data) */\nconst draft = Array.isArray(items[0].json)\n ? items[0].json[0]\n : items[0].json;\n\n/* 1. candidates: если строка → JSON.parse */\nconst candidates = typeof draft.candidates === 'string'\n ? JSON.parse(draft.candidates)\n : draft.candidates || [];\n\n/* 2. индекс альтернативы */\nconst idx = $json.alt_idx ?? 0;\nconst cand = candidates[idx] || { dish:'(не найдено)', grams: draft.grams_pred || 200 };\n\n/* 3. считаем кнопки веса */\nconst g = cand.grams;\nconst step = g < 120 ? 20 : 50;\nconst btns = [g-step, g, g+step].filter(x=>x>0);\n\nreturn [{\n json:{\n chat_id : draft.chat_id,\n draft_id : draft.message_id, // пригодится для UPDATE\n dish_ru : cand.dish,\n grams_est : g,\n buttons : btns.map(x=>({\n text : `${x} г`,\n data : `weight_${x}_${draft.message_id}`\n }))\n }\n}];\n"},"type":"n8n-nodes-base.code","typeVersion":2,"position":[592,528],"id":"99b613d9-8bea-47eb-95ef-09f3ca01c653","name":"WEIGHT 1","alwaysOutputData":true},{"parameters":{"jsCode":"/**\n * Упрощаем: код лишь формирует данные,\n * а финальный текст собираем прямо в Telegram-узле.\n */\n\n// 0. Достаём draft (учёт Always-Output Data)\nconst raw = items[0].json[0] ?? items[0].json;\n\n// 1. Парсим candidates, если пришла строкой\nconst candidates = typeof raw.candidates === 'string'\n ? JSON.parse(raw.candidates)\n : raw.candidates || [];\n\n// 2. Берём альтернативы (макс. 3) — без первого\nconst alts = candidates.slice(1, 4);\n\n// 3. Подготовим «красивые» строки для списка\nconst altLines = alts.map((c, i) => `${i + 1}. ${c.dish}`);\n\n// 4. Кнопки 1-2-3\nconst buttons = alts.map((_, i) => ({\n text : String(i + 1),\n data : `alt_${i}_${raw.message_id}`,\n}));\n\nreturn [{\n json: {\n chat_id : raw.chat_id,\n draft_id : raw.message_id,\n\n // для Telegram-узла\n alt_lines : altLines, // массив ['1. …', '2. …', …]\n buttons, // inline-кнопки\n },\n}];\n"},"type":"n8n-nodes-base.code","typeVersion":2,"position":[592,848],"id":"faa2cbcc-c0c4-4d9f-a899-b25b12140f9d","name":"MORE","alwaysOutputData":true},{"parameters":{"tableId":"meals","fieldsUi":{"fieldValues":[{"fieldId":"chat_id","fieldValue":"={{$json.chat_id}}"},{"fieldId":"dish","fieldValue":"={{ $json.dish }}"},{"fieldId":"grams","fieldValue":"={{ $json.grams }}"},{"fieldId":"eaten_at","fieldValue":"={{ $json.eaten_at }}"},{"fieldId":"kcal","fieldValue":"={{ $json.kcal }}"},{"fieldId":"fat","fieldValue":"={{ $json.fat }}"},{"fieldId":"carb","fieldValue":"={{ $json.carb }}"},{"fieldId":"prot","fieldValue":"={{ $json.prot }}"}]}},"type":"n8n-nodes-base.supabase","typeVersion":1,"position":[1392,1440],"id":"b2dd0185-0ef8-470b-b55d-07c25d8738cf","name":"CREATE meals","credentials":{"supabaseApi":{"id":"OoOx3pPUNd1lRJTr","name":"Supabase account"}}},{"parameters":{"jsCode":"// Пример callback_data: dish_yes_7\nconst parts = $json.callback_query.data.split('_');\nconst draftId = parts.pop(); // '7'\n\n// ID сообщения с кнопками «Да / Нет»,\n// которое нужно удалить после обработки\nconst delMsgId = $json.callback_query.message.message_id;\n\nreturn [{\n json: {\n draft_id : Number(draftId), // 7\n chat_id : $json.callback_query.from.id, // 7758…\n del_msg_id : delMsgId // для Delete-узла\n }\n}];\n"},"type":"n8n-nodes-base.code","typeVersion":2,"position":[64,528],"id":"cf73cd44-91a1-4171-8026-83c6580581a3","name":"Parse dish_YES"},{"parameters":{"jsCode":"// Пример callback_data: dish_yes_7\nconst parts = $json.callback_query.data.split('_');\nconst draftId = parts.pop(); // '7'\n\n// ID сообщения с кнопками «Да / Нет»,\n// которое нужно удалить после обработки\nconst delMsgId = $json.callback_query.message.message_id;\n\nreturn [{\n json: {\n draft_id : Number(draftId), // 7\n chat_id : $json.callback_query.from.id, // 7758…\n del_msg_id : delMsgId // для Delete-узла\n }\n}];\n"},"type":"n8n-nodes-base.code","typeVersion":2,"position":[64,848],"id":"0a101f1a-66ca-4a87-9eaa-791cb1bafb35","name":"Parse dish_NO"},{"parameters":{"jsCode":"// Parse macros (замена текущего кода)\nconst sw = $items('Split weight')[0].json; // chat_id, grams, draft_id …\n\n// assistant.content уже объект: dish, kcal, prot, …\nconst gpt = $json.message?.content ?? $json; // на случай, если jsonOutput=false\n\nconst toMsk = () => {\n const msk = new Date(new Date().toLocaleString('en-US',{timeZone:'Europe/Moscow'}));\n const p = n => String(n).padStart(2,'0');\n return `${msk.getFullYear()}-${p(msk.getMonth()+1)}-${p(msk.getDate())}` +\n `T${p(msk.getHours())}:${p(msk.getMinutes())}:00+03:00`;\n};\n\nreturn [{\n json: {\n ...sw, // chat_id, grams …\n ...gpt, // dish, kcal, prot …\n eaten_at: toMsk()\n }\n}];\n"},"type":"n8n-nodes-base.code","typeVersion":2,"position":[1168,1520],"id":"cc5abefe-1e43-4393-b223-602774224696","name":"Parse macros"},{"parameters":{},"type":"n8n-nodes-base.merge","typeVersion":3.1,"position":[672,1520],"id":"2f88a2f3-5971-414f-9684-d1d37e81387b","name":"Merge"},{"parameters":{"resource":"file","fileId":"={{ $json.photo_file_id }}","additionalFields":{}},"id":"7580a5f0-c838-4dab-9f48-38a534309e31","name":"Get Image","type":"n8n-nodes-base.telegram","position":[224,128],"typeVersion":1.2,"webhookId":"8b210039-e135-420d-a5f1-53fc3ca1e836","retryOnFail":false,"maxTries":2,"credentials":{"telegramApi":{"id":"R8VDF53JH3mzhoHd","name":"Telegram dieta"}}},{"parameters":{"operation":"toBinary","sourceProperty":"data","options":{"fileName":"={{ $json.result.file_path }}"}},"id":"e9990056-5926-4dc3-a4f5-c1a7db679dcd","name":"Convert","type":"n8n-nodes-base.convertToFile","position":[624,128],"typeVersion":1.1},{"parameters":{"jsCode":"/**\n * Берём исходный update из триггера\n */\nconst upd = $items(\"Telegram Trigger\")[0].json.message;\nconst chatId = upd.chat.id;\nconst msgId = upd.message_id;\nconst photoId = upd.photo[upd.photo.length - 1].file_id;\n\n/**\n * Русский JSON от Vision\n */\nconst vision = JSON.parse(($json.content || '').replace(/```/g, '').trim());\nconst candidates = vision.candidates || [];\nconst first = candidates[0] || { dish:'блюдо', grams:0 };\n\n/**\n * Draftобъект\n */\nreturn [{\n json: {\n chat_id : chatId,\n message_id : msgId,\n photo_file_id : photoId,\n\n candidates, // массив на русском\n grams_pred : first.grams,\n status : 'await_dish',\n\n text : `Это *${first.dish}*?`,\n cb_yes : `dish_yes_${msgId}`,\n cb_no : `dish_no_${msgId}`\n }\n}];\n"},"type":"n8n-nodes-base.code","typeVersion":2,"position":[1024,128],"id":"890d69b4-2a3d-4d4b-ab5a-1abd06bff9d6","name":"Parse Vision"},{"parameters":{"assignments":{"assignments":[{"id":"bd8a8c20-939e-49b0-93d0-bb58b8719ebb","name":"chat_id","value":"={{ $json.message.chat.id }}","type":"string"},{"id":"f89d0646-9f73-4067-bbf7-af9913b5f688","name":"message_id","value":"={{$json.message.message_id}}","type":"string"},{"id":"07282534-971f-4430-8d45-5f3e15d3c167","name":"photo_file_id","value":"={{$json.message.photo[$json.message.photo.length - 1].file_id}}","type":"string"}]},"options":{}},"type":"n8n-nodes-base.set","typeVersion":3.4,"position":[64,128],"id":"5752a827-6495-47b2-b8ab-9b5495d264c2","name":"Get ready"},{"parameters":{"chatId":"={{ $json.chat_id }}","text":"={{ $json.text }}","replyMarkup":"inlineKeyboard","inlineKeyboard":{"rows":[{"row":{"buttons":[{"text":"Да","additionalFields":{"callback_data":"={{$json.cb_yes}}"}},{"text":"Нет","additionalFields":{"callback_data":"={{$json.cb_no}}"}}]}}]},"additionalFields":{"appendAttribution":false}},"type":"n8n-nodes-base.telegram","typeVersion":1.2,"position":[1440,224],"id":"9dc2e33f-38ee-45c1-9cc7-adb282d1331c","name":"dish YES or NO","webhookId":"dc6a9f65-91bd-46e4-8c95-17b2ebe68d7c","credentials":{"telegramApi":{"id":"R8VDF53JH3mzhoHd","name":"Telegram dieta"}}},{"parameters":{"tableId":"meals_draft","fieldsUi":{"fieldValues":[{"fieldId":"chat_id","fieldValue":"={{ $json.chat_id }}"},{"fieldId":"message_id","fieldValue":"={{ $json.message_id }}"},{"fieldId":"photo_file_id","fieldValue":"={{ $json.photo_file_id }}"},{"fieldId":"candidates","fieldValue":"={{ $json.candidates }}"},{"fieldId":"grams_pred","fieldValue":"={{ $json.grams_pred }}"},{"fieldId":"status","fieldValue":"={{ $json.status }}"},{"fieldId":"created_at","fieldValue":"={{ new Date().toISOString() }}"}]}},"type":"n8n-nodes-base.supabase","typeVersion":1,"position":[1440,48],"id":"5620bf9d-a9dc-4504-baa7-a837ce33a204","name":"CREATE candidates","credentials":{"supabaseApi":{"id":"OoOx3pPUNd1lRJTr","name":"Supabase account"}}},{"parameters":{"assignments":{"assignments":[{"id":"360c7be2-b049-4c62-bb83-5fafd0850722","name":"chat_id","value":"={{$json.chat_id}}","type":"string"},{"id":"584b9ab5-5ba9-42f9-a9d9-7bb9bb115361","name":"message_id","value":"={{$json.message_id}}","type":"string"},{"id":"8d7a3167-4cbb-4051-8c23-a0b88438c815","name":"photo_file_id","value":"={{$json.photo_file_id}}","type":"string"},{"id":"246a834e-e731-4239-aa92-60eb7c75d79f","name":"candidates","value":"={{$json.candidates}}","type":"string"},{"id":"69f21e55-55ef-4cf0-b73d-b3e39144e057","name":"grams_pred","value":"={{$json.grams_pred}}","type":"string"},{"id":"1b41e033-b7ce-47b0-8f57-0f8dc109ecab","name":"status","value":"={{$json.status}}","type":"string"}]},"includeOtherFields":true,"options":{}},"type":"n8n-nodes-base.set","typeVersion":3.4,"position":[1264,48],"id":"daf38393-7e4a-4a65-b106-772a023d6d36","name":"EDIT candidates"},{"parameters":{"content":"# ФОТО БЛЮДА = 1 ВАРИАНТ","height":392,"width":1698,"color":6},"id":"4ea9bc63-fda6-4c02-9b5e-69c2e054c18c","name":"Sticky Note3","type":"n8n-nodes-base.stickyNote","position":[0,0],"typeVersion":1},{"parameters":{"method":"POST","url":"https://api.telegram.org/botKEY/sendChatAction","sendBody":true,"bodyParameters":{"parameters":[{"name":"chat_id","value":"={{ $json.message.from.id }}"},{"name":"action","value":"typing"}]},"options":{}},"type":"n8n-nodes-base.httpRequest","typeVersion":4.2,"position":[-416,848],"id":"bf3b7eb3-2a56-448f-b354-9bf96ec4573b","name":"HTTP typing...","alwaysOutputData":true,"onError":"continueRegularOutput"},{"parameters":{"operation":"binaryToPropery","options":{}},"id":"dc25033a-af2e-459b-b776-c1dbf7e3d394","name":"Extract","type":"n8n-nodes-base.extractFromFile","position":[464,128],"typeVersion":1},{"parameters":{"workflowId":{"__rl":true,"value":"kohwX0oaY0hmL9b2","mode":"list","cachedResultUrl":"/workflow/kohwX0oaY0hmL9b2","cachedResultName":"tx_text"},"workflowInputs":{"mappingMode":"defineBelow","value":{},"matchingColumns":[],"schema":[],"attemptToConvertTypes":false,"convertFieldsToString":true},"options":{"waitForSubWorkflow":true}},"type":"n8n-nodes-base.executeWorkflow","typeVersion":1.2,"position":[112,2288],"id":"8b0bbc63-fa92-47e8-a5d7-3bdcbd32b290","name":"tg_text"},{"parameters":{"content":"# ТЕКСТ и /\n","height":312,"width":318,"color":7},"id":"d14cf488-d3a0-4208-be12-bc9393b478bf","name":"Sticky Note4","type":"n8n-nodes-base.stickyNote","position":[0,2192],"typeVersion":1},{"parameters":{"content":"# НЕ СОХРАНЯТЬ\n","height":312,"width":958,"color":7},"id":"8af20db1-b8f7-48ce-a64d-249d904bb5ea","name":"Sticky Note6","type":"n8n-nodes-base.stickyNote","position":[0,1840],"typeVersion":1},{"parameters":{"jsCode":"// cancel_62\nconst mealId = Number($json.callback_query.data.split('_').pop());\n\nreturn [{\n json:{\n meal_id : mealId,\n chat_id : $json.callback_query.from.id,\n msg_id : $json.callback_query.message.message_id\n }\n}];\n"},"type":"n8n-nodes-base.code","typeVersion":2,"position":[64,1952],"id":"d7043f72-4a21-469f-8058-ade0923d49eb","name":"Parse cancel"},{"parameters":{"operation":"update","tableId":"meals","matchType":"allFilters","filters":{"conditions":[{"keyName":"id","condition":"eq","keyValue":"={{ $json.meal_id }}"},{"keyName":"chat_id","condition":"eq","keyValue":"={{$json.chat_id}}"}]},"fieldsUi":{"fieldValues":[{"fieldId":"deleted","fieldValue":"true"}]}},"type":"n8n-nodes-base.supabase","typeVersion":1,"position":[240,1952],"id":"2d342f15-4653-4e0e-9e3e-f841eaed6772","name":"UPDATE meals","alwaysOutputData":true,"credentials":{"supabaseApi":{"id":"OoOx3pPUNd1lRJTr","name":"Supabase account"}}},{"parameters":{"operation":"get","tableId":"meals","filters":{"conditions":[{"keyName":"chat_id","keyValue":"={{ $json.chat_id }}"},{"keyName":"id","keyValue":"={{ $json.id }}"}]}},"type":"n8n-nodes-base.supabase","typeVersion":1,"position":[400,1952],"id":"6141812b-9efd-40bb-ae6e-184b42149a92","name":"GET meals","alwaysOutputData":true,"credentials":{"supabaseApi":{"id":"OoOx3pPUNd1lRJTr","name":"Supabase account"}}},{"parameters":{"jsCode":"const row = $items('GET meals')[0].json; // dish, grams, kcal …\nconst ctx = $items('Parse cancel')[0].json; // chat_id, msg_id\n\nreturn [{\n json: {\n chat_id : ctx.chat_id,\n msg_id : ctx.msg_id,\n\n // что пойдёт в текст\n dish : row.dish,\n grams : row.grams,\n kcal : row.kcal,\n prot : row.prot,\n fat : row.fat,\n carb : row.carb\n }\n}];\n"},"type":"n8n-nodes-base.code","typeVersion":2,"position":[560,1952],"id":"854e0904-640e-412d-8a48-8c569e498b17","name":"build cancel"},{"parameters":{"operation":"editMessageText","chatId":"={{ $json.chat_id }}","messageId":"={{ $json.msg_id }}","text":"=*{{ $json.dish }} {{ $json.grams }} г*\n\n*Калорий:* {{ $json.kcal }}\n*Б:* {{ $json.prot }}*Ж:* {{ $json.fat }}*У:* {{ $json.carb }}\n\n🚫 _не сохранил_\n","additionalFields":{"parse_mode":"Markdown"}},"type":"n8n-nodes-base.telegram","typeVersion":1.2,"position":[752,1952],"id":"0d8a0b50-ff67-4170-99d4-7d4aadca132b","name":"EDITED","webhookId":"d03fb55d-8c26-4782-92a9-d0c9c351a440","credentials":{"telegramApi":{"id":"R8VDF53JH3mzhoHd","name":"Telegram dieta"}}},{"parameters":{"resource":"image","operation":"analyze","modelId":{"__rl":true,"value":"chatgpt-4o-latest","mode":"list","cachedResultName":"CHATGPT-4O-LATEST"},"text":"\nТы пищевой классификатор.\nВерни JSON ТОЛЬКО на русском, без ``` :\n\n{\n \"candidates\": [\n { \"dish\": \"строка\", \"grams\": число, \"confidence\": 01 },\n … максимум 3\n ]\n}\n","inputType":"base64","options":{}},"type":"@n8n/n8n-nodes-langchain.openAi","typeVersion":1.8,"position":[864,128],"id":"4b235725-e5af-430b-8201-aa5984a0476b","name":"VISION","retryOnFail":true,"notesInFlow":false,"executeOnce":false,"credentials":{"openAiApi":{"id":"PvUURuR361IXH0ve","name":"OpenAi account"}}},{"parameters":{"modelId":{"__rl":true,"value":"chatgpt-4o-latest","mode":"list","cachedResultName":"CHATGPT-4O-LATEST"},"messages":{"values":[{"content":"=Ты нутри-калькулятор. \nНа вход получаешь JSON \n{ \"dish\":\"строка\", \"grams\":число }. \n\nОтвечай строго JSON одной строкой:\n\n{\n \"dish\":\"строка\",\n \"kcal\":число,\n \"prot\":число,\n \"fat\":число,\n \"carb\":число\n}\n\nБез пояснений, без ```.","role":"system"},{"content":"={{ $json.chosen_name }}, {{ $json.grams_pred }}"}]},"jsonOutput":true,"options":{}},"type":"@n8n/n8n-nodes-langchain.openAi","typeVersion":1.8,"position":[832,1520],"id":"0586f799-bd0a-4089-bce3-7b859600e557","name":"NUTRION","credentials":{"openAiApi":{"id":"PvUURuR361IXH0ve","name":"OpenAi account"}}},{"parameters":{"model":"openai/gpt-4o","options":{}},"type":"@n8n/n8n-nodes-langchain.lmChatOpenRouter","typeVersion":1,"position":[2288,1632],"id":"52ddcbd7-9829-4590-9eff-879a11bc72e9","name":"OpenRouter Chat Model","disabled":true},{"parameters":{"jsonSchemaExample":"{\n \"dish\": \"овощной салат с сыром\",\n \"kcal\": 122,\n \"prot\": 3.8,\n \"fat\": 8.2,\n \"carb\": 9.2\n}\n"},"type":"@n8n/n8n-nodes-langchain.outputParserStructured","typeVersion":1.2,"position":[2432,1632],"id":"ca89f1d7-5f6e-474e-9987-a89ee34da567","name":"Structured Output Parser","disabled":true},{"parameters":{"jsCode":"/**\n * Parse macros (универсально для:\n * старого jsonOutput: true\n * нового Structured Output Parser c массивом или без)\n */\n\n// 1. данные от Split weight (chat_id, grams, draft_id, …)\nconst sw = $items('Split weight')[0].json;\n\n// 2. что пришло от LLM / parser\n// если это массив → берём первый элемент\n// если внутри есть .output → берём его, иначе сам объект\nconst raw = Array.isArray($json) ? $json[0] : $json;\nconst gpt = raw.output ?? raw; // { dish, kcal, prot, fat, carb }\n\n// 3. helper → строка даты-времени в МСК ISO +03:00\nconst toMsk = () => {\n const msk = new Date(\n new Date().toLocaleString('en-US', { timeZone: 'Europe/Moscow' })\n );\n const p = n => String(n).padStart(2, '0');\n return `${msk.getFullYear()}-${p(msk.getMonth() + 1)}-${p(msk.getDate())}` +\n `T${p(msk.getHours())}:${p(msk.getMinutes())}:00+03:00`;\n};\n\n// 4. собираем итоговый объект (плоский)\nreturn [{\n json: {\n ...sw, // chat_id, grams, draft_id, …\n ...gpt, // dish, kcal, prot, fat, carb\n eaten_at: toMsk()\n }\n}];\n"},"type":"n8n-nodes-base.code","typeVersion":2,"position":[2624,1488],"id":"dad7038f-a082-4adc-b9a5-329cc2ad5e23","name":"Parse macros 2","disabled":true},{"parameters":{"promptType":"define","text":"={{ $json.chosen_name }}, {{ $json.grams_pred }}","hasOutputParser":true,"options":{"systemMessage":"Ты нутри-калькулятор. \nНа вход получаешь JSON \n{ \"dish\":\"строка\", \"grams\":число }. \n\nОтвечай строго JSON одной строкой:\n\n{\n \"dish\":\"строка\",\n \"kcal\":число,\n \"prot\":число,\n \"fat\":число,\n \"carb\":число\n}\n\nБез пояснений, без ```."}},"type":"@n8n/n8n-nodes-langchain.agent","typeVersion":1.9,"position":[2272,1488],"id":"1bf73b9a-6682-4bd7-9430-cbc841a65382","name":"NUTRION OR","disabled":true},{"parameters":{"operation":"get","tableId":"meals_draft","filters":{"conditions":[{"keyName":"chat_id","keyValue":"={{$json.chat_id}}"},{"keyName":"message_id","keyValue":"={{$json.draft_id}}"},{"keyName":"status","keyValue":"=await_dish"}]}},"type":"n8n-nodes-base.supabase","typeVersion":1,"position":[448,1600],"id":"6e3168d4-961c-4d8c-b347-faa580776f96","name":"GET await_dish","alwaysOutputData":false,"credentials":{"supabaseApi":{"id":"OoOx3pPUNd1lRJTr","name":"Supabase account"}}},{"parameters":{"operation":"get","tableId":"meals_draft","filters":{"conditions":[{"keyName":"chat_id","keyValue":"={{$json.chat_id}}"},{"keyName":"message_id","keyValue":"={{$json.draft_id}}"},{"keyName":"status","keyValue":"await_weight"}]}},"type":"n8n-nodes-base.supabase","typeVersion":1,"position":[448,1440],"id":"cb7cc959-621d-4fb0-874b-f10e96b7e39e","name":"GET await_weight","alwaysOutputData":false,"credentials":{"supabaseApi":{"id":"OoOx3pPUNd1lRJTr","name":"Supabase account"}}},{"parameters":{"content":"### другая LLM\n\n\n","height":392,"width":618,"color":5},"id":"45f631a8-6840-4219-a084-a0fb861a3ac8","name":"Sticky Note7","type":"n8n-nodes-base.stickyNote","position":[2192,1408],"typeVersion":1}],"connections":{"Telegram Trigger":{"main":[[{"node":"Switch","type":"main","index":0},{"node":"HTTP typing...","type":"main","index":0}]]},"Switch":{"main":[[],[{"node":"Get ready","type":"main","index":0}],[{"node":"Parse dish_YES","type":"main","index":0}],[{"node":"Parse dish_NO","type":"main","index":0}],[{"node":"Parse alt","type":"main","index":0}],[{"node":"Split weight","type":"main","index":0}],[{"node":"Parse cancel","type":"main","index":0}],[{"node":"tg_text","type":"main","index":0}]]},"Parse alt":{"main":[[{"node":"GET 3","type":"main","index":0},{"node":"DEL await_alt","type":"main","index":0}]]},"GET 3":{"main":[[{"node":"WEIGHT 3","type":"main","index":0}]]},"GET 2":{"main":[[{"node":"MORE","type":"main","index":0}]]},"GET 1":{"main":[[{"node":"WEIGHT 1","type":"main","index":0}]]},"Split weight":{"main":[[{"node":"DEL await_weight","type":"main","index":0},{"node":"GET await_dish","type":"main","index":0},{"node":"GET await_weight","type":"main","index":0}]]},"WEIGHT 3":{"main":[[{"node":"UPDATE 3","type":"main","index":0},{"node":"await_weight 3","type":"main","index":0}]]},"WEIGHT 1":{"main":[[{"node":"await_weight 1","type":"main","index":0},{"node":"UPDATE 1","type":"main","index":0}]]},"MORE":{"main":[[{"node":"await_alt","type":"main","index":0},{"node":"UPDATE 2","type":"main","index":0}]]},"Parse dish_YES":{"main":[[{"node":"GET 1","type":"main","index":0},{"node":"DEL dish_yes","type":"main","index":0}]]},"Parse dish_NO":{"main":[[{"node":"GET 2","type":"main","index":0},{"node":"DEL dish_no","type":"main","index":0}]]},"Parse macros":{"main":[[{"node":"UPDATE 4","type":"main","index":0},{"node":"CREATE meals","type":"main","index":0}]]},"Merge":{"main":[[{"node":"NUTRION","type":"main","index":0}]]},"Get Image":{"main":[[{"node":"Extract","type":"main","index":0}]]},"Convert":{"main":[[{"node":"VISION","type":"main","index":0}]]},"Parse Vision":{"main":[[{"node":"EDIT candidates","type":"main","index":0},{"node":"dish YES or NO","type":"main","index":0}]]},"Get ready":{"main":[[{"node":"Get Image","type":"main","index":0}]]},"EDIT candidates":{"main":[[{"node":"CREATE candidates","type":"main","index":0}]]},"Extract":{"main":[[{"node":"Convert","type":"main","index":0}]]},"Parse cancel":{"main":[[{"node":"UPDATE meals","type":"main","index":0}]]},"UPDATE meals":{"main":[[{"node":"GET meals","type":"main","index":0}]]},"GET meals":{"main":[[{"node":"build cancel","type":"main","index":0}]]},"build cancel":{"main":[[{"node":"EDITED","type":"main","index":0}]]},"CREATE meals":{"main":[[{"node":"DONE","type":"main","index":0}]]},"VISION":{"main":[[{"node":"Parse Vision","type":"main","index":0}]]},"NUTRION":{"main":[[{"node":"Parse macros","type":"main","index":0}]]},"OpenRouter Chat Model":{"ai_languageModel":[[{"node":"NUTRION OR","type":"ai_languageModel","index":0}]]},"Structured Output Parser":{"ai_outputParser":[[{"node":"NUTRION OR","type":"ai_outputParser","index":0}]]},"NUTRION OR":{"main":[[{"node":"Parse macros 2","type":"main","index":0}]]},"GET await_dish":{"main":[[{"node":"Merge","type":"main","index":1}]]},"GET await_weight":{"main":[[{"node":"Merge","type":"main","index":0}]]}},"settings":{"executionOrder":"v1"},"staticData":null,"meta":null,"pinData":{},"versionId":"df708ee1-5b21-4094-8656-93c821012ed9","activeVersionId":null,"triggerCount":1,"shared":[{"updatedAt":"2025-11-30T14:22:03.470Z","createdAt":"2025-11-30T14:22:03.470Z","role":"workflow:owner","workflowId":"jZIoYr8RW41K0j4J","projectId":"sYuiFAb87pAir6jV"}],"activeVersion":null,"tags":[]}