{ "name": "Docker Event - Callback Handler", "nodes": [ { "parameters": { "updates": ["callback_query"] }, "type": "n8n-nodes-base.telegramTrigger", "typeVersion": 1.2, "position": [0, 0], "id": "telegram-trigger", "name": "Telegram Trigger" }, { "parameters": { "jsCode": "const callback = $input.first().json;\nconst data = callback.callback_query?.data || '';\nconst chatId = callback.callback_query?.from?.id;\nconst messageId = callback.callback_query?.message?.message_id;\n\n// Parse: auto:slug, manual:slug, ignore:slug\nconst [action, slug] = data.split(':');\n\nreturn [{\n json: {\n action,\n slug,\n chatId,\n messageId,\n rawCallback: data\n }\n}];" }, "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [220, 0], "id": "parse-callback", "name": "Parse Callback" }, { "parameters": { "rules": { "values": [ { "conditions": { "options": { "caseSensitive": true, "leftValue": "" }, "conditions": [ { "leftValue": "={{ $json.action }}", "rightValue": "auto", "operator": { "type": "string", "operation": "equals" } } ], "combinator": "and" }, "renameOutput": true, "outputKey": "Auto" }, { "conditions": { "options": { "caseSensitive": true, "leftValue": "" }, "conditions": [ { "leftValue": "={{ $json.action }}", "rightValue": "manual", "operator": { "type": "string", "operation": "equals" } } ], "combinator": "and" }, "renameOutput": true, "outputKey": "Manual" }, { "conditions": { "options": { "caseSensitive": true, "leftValue": "" }, "conditions": [ { "leftValue": "={{ $json.action }}", "rightValue": "ignore", "operator": { "type": "string", "operation": "equals" } } ], "combinator": "and" }, "renameOutput": true, "outputKey": "Ignore" } ] }, "options": {} }, "type": "n8n-nodes-base.switch", "typeVersion": 3.2, "position": [440, 0], "id": "switch-action", "name": "Switch Action" }, { "parameters": { "url": "=https://cms.dk0.dev/items/projects?filter[slug][_eq]={{ $json.slug }}&limit=1", "authentication": "predefinedCredentialType", "nodeCredentialType": "httpBearerAuth", "options": {} }, "type": "n8n-nodes-base.httpRequest", "typeVersion": 4.4, "position": [660, -200], "id": "get-project-data", "name": "Get Project from CMS" }, { "parameters": { "url": "=https://git.dk0.dev/api/v1/repos/denshooter/{{ $json.slug }}/commits?limit=3", "authentication": "genericCredentialType", "genericAuthType": "httpHeaderAuth", "options": {} }, "type": "n8n-nodes-base.httpRequest", "typeVersion": 4.4, "position": [880, -280], "id": "get-commits-auto", "name": "Get Commits" }, { "parameters": { "url": "=https://git.dk0.dev/api/v1/repos/denshooter/{{ $json.slug }}/contents/README.md", "authentication": "genericCredentialType", "genericAuthType": "httpHeaderAuth", "options": {} }, "type": "n8n-nodes-base.httpRequest", "typeVersion": 4.4, "position": [880, -160], "id": "get-readme-auto", "name": "Get README" }, { "parameters": { "model": "openrouter/free", "options": {} }, "type": "@n8n/n8n-nodes-langchain.lmChatOpenRouter", "typeVersion": 1, "position": [1320, -100], "id": "openrouter-model-auto", "name": "OpenRouter Chat Model" }, { "parameters": { "promptType": "define", "text": "=Du bist ein technischer Autor für das Portfolio von Dennis (dk0.dev).\n\nNeues eigenes Projekt deployed:\nRepo: {{ $('Parse Callback').item.json.slug }}\n\nREADME:\n{{ $('Get README').first().json.content ? Buffer.from($('Get README').first().json.content, 'base64').toString('utf8').substring(0, 1000) : 'Kein README' }}\n\nLetzte Commits:\n{{ $('Get Commits').first().json.map(c => '- ' + c.commit.message).join('\\n') }}\n\nErstelle eine Portfolio-Beschreibung:\n- Was macht das Projekt (Features, Zweck)\n- Tech-Stack und Architektur\n- Highlights aus den Commits\n- Warum ist es cool/interessant\n\nKategorie: webdev (wenn Web-App), automation (wenn Tool/Script), oder selfhosted\n\nAntworte NUR als JSON:\n{\n \"title_en\": \"Aussagekräftiger Titel\",\n \"title_de\": \"Aussagekräftiger Titel\",\n \"description_en\": \"4-6 Sätze\",\n \"description_de\": \"4-6 Sätze\",\n \"content_en\": \"2-3 Absätze Markdown mit technischen Details\",\n \"content_de\": \"2-3 Absätze Markdown mit technischen Details\",\n \"category\": \"webdev|automation|selfhosted\",\n \"technologies\": [\"Next.js\", \"Docker\", \"...\"]\n}" }, "type": "@n8n/n8n-nodes-langchain.chainLlm", "typeVersion": 1.9, "position": [1100, -200], "id": "ai-auto", "name": "AI: Generate Description" }, { "parameters": { "jsCode": "const raw = $input.first().json.text ?? \"\";\nconst match = raw.match(/\\{[\\s\\S]*\\}/);\nif (!match) throw new Error(\"No JSON found\");\nconst ai = JSON.parse(match[0]);\nreturn [{ json: ai }];" }, "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [1320, -200], "id": "parse-json-auto", "name": "Parse JSON" }, { "parameters": { "jsCode": "const ai = $input.first().json;\nconst ctx = $('Parse Callback').first().json;\n\nconst body = {\n slug: ctx.slug,\n status: \"draft\",\n featured: false,\n title: ai.title_en,\n category: ai.category,\n technologies: ai.technologies,\n tags: ai.technologies,\n date: new Date().toISOString().slice(0, 10),\n translations: {\n create: [\n {\n languages_code: \"en-US\",\n title: ai.title_en,\n description: ai.description_en,\n content: ai.content_en\n },\n {\n languages_code: \"de-DE\",\n title: ai.title_de,\n description: ai.description_de,\n content: ai.content_de\n }\n ]\n }\n};\n\nconst response = await this.helpers.httpRequest({\n method: \"POST\",\n url: \"https://cms.dk0.dev/items/projects\",\n headers: {\n \"Content-Type\": \"application/json\",\n \"Authorization\": \"Bearer RF2QytqhcLXuVy6FO3PzWlsoR-ysCTwB\"\n },\n body\n});\n\nreturn [{ json: response }];" }, "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [1540, -200], "id": "add-to-directus-auto", "name": "Add to Directus" }, { "parameters": { "chatId": "={{ $('Parse Callback').item.json.chatId }}", "text": "={{ \n'✅ Projekt erstellt: ' + $json.data.title + '\\n\\n' +\n'📝 ' + $('Parse JSON').first().json.description_de.substring(0, 200) + '...\\n\\n' +\n'Status: Draft (ID: ' + $json.data.id + ')\\n\\n' +\n'/publishproject' + $json.data.id + ' — Veröffentlichen\\n' + \n'/deleteproject' + $json.data.id + ' — Löschen' \n}}", "additionalFields": {} }, "type": "n8n-nodes-base.telegram", "typeVersion": 1.2, "position": [1760, -200], "id": "telegram-notify-auto", "name": "Notify Success" }, { "parameters": { "chatId": "={{ $json.chatId }}", "text": "✍️ OK, schreib mir jetzt was das Projekt macht (4-6 Sätze).\n\nIch formatiere das dann schön und erstelle einen Draft.", "additionalFields": {} }, "type": "n8n-nodes-base.telegram", "typeVersion": 1.2, "position": [660, 0], "id": "telegram-ask-manual", "name": "Ask for Manual Input" }, { "parameters": { "chatId": "={{ $json.chatId }}", "text": "❌ OK, ignoriert.", "additionalFields": {} }, "type": "n8n-nodes-base.telegram", "typeVersion": 1.2, "position": [660, 200], "id": "telegram-ignore", "name": "Confirm Ignore" } ], "connections": { "Telegram Trigger": { "main": [[{ "node": "Parse Callback", "type": "main", "index": 0 }]] }, "Parse Callback": { "main": [[{ "node": "Switch Action", "type": "main", "index": 0 }]] }, "Switch Action": { "main": [ [{ "node": "Get Project from CMS", "type": "main", "index": 0 }], [{ "node": "Ask for Manual Input", "type": "main", "index": 0 }], [{ "node": "Confirm Ignore", "type": "main", "index": 0 }] ] }, "Get Project from CMS": { "main": [[{ "node": "Get Commits", "type": "main", "index": 0 }]] }, "Get Commits": { "main": [[{ "node": "Get README", "type": "main", "index": 0 }]] }, "Get README": { "main": [[{ "node": "AI: Generate Description", "type": "main", "index": 0 }]] }, "OpenRouter Chat Model": { "ai_languageModel": [[{ "node": "AI: Generate Description", "type": "ai_languageModel", "index": 0 }]] }, "AI: Generate Description": { "main": [[{ "node": "Parse JSON", "type": "main", "index": 0 }]] }, "Parse JSON": { "main": [[{ "node": "Add to Directus", "type": "main", "index": 0 }]] }, "Add to Directus": { "main": [[{ "node": "Notify Success", "type": "main", "index": 0 }]] } }, "active": false, "settings": { "executionOrder": "v1" }, "id": "docker-event-callback" }