{ "name": "Telegram Assistant - Deck Integration", "active": false, "nodes": [ { "parameters": { "httpMethod": "POST", "path": "telegram-deck", "responseMode": "responseNode", "options": {} }, "id": "webhook-deck-1", "name": "Webhook", "type": "n8n-nodes-base.webhook", "typeVersion": 1.1, "position": [ 240, 300 ], "webhookId": "telegram-deck" }, { "parameters": { "mode": "runOnceForEachItem", "jsCode": "// Parse deck command\nconst args = $input.item.json.args || '';\nconst chatId = $input.item.json.chatId;\n\n// Extract subcommand\nconst parts = args.trim().split(/\\s+/);\nconst subCommand = parts[0]?.toLowerCase() || 'help';\nconst taskText = parts.slice(1).join(' ');\n\nreturn {\n chatId: chatId,\n subCommand: subCommand,\n taskText: taskText,\n originalArgs: args\n};" }, "id": "parse-deck-command-1", "name": "Parse Deck Command", "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [ 460, 300 ] }, { "parameters": { "dataType": "string", "value1": "={{ $json.subCommand }}", "rules": { "rules": [ { "value2": "add", "output": 0 }, { "value2": "list", "output": 1 } ] }, "fallbackOutput": 2 }, "id": "switch-deck-action-1", "name": "Route Deck Action", "type": "n8n-nodes-base.switch", "typeVersion": 3, "position": [ 680, 300 ] }, { "parameters": { "conditions": { "string": [ { "value1": "={{ $json.taskText }}", "operation": "isNotEmpty" } ] } }, "id": "check-task-text-1", "name": "Check Task Text", "type": "n8n-nodes-base.if", "typeVersion": 1, "position": [ 900, 200 ] }, { "parameters": { "url": "https://api.openai.com/v1/chat/completions", "authentication": "predefinedCredentialType", "nodeCredentialType": "openAiApi", "sendHeaders": true, "headerParameters": { "parameters": [ { "name": "Authorization", "value": "=Bearer {{ $credentials.openai_api_key }}" } ] }, "sendBody": true, "specifyBody": "json", "jsonBody": "={\n \"model\": \"gpt-4o-mini\",\n \"messages\": [\n {\n \"role\": \"system\",\n \"content\": \"Extract task information from user input. Return JSON with: title (required, concise task name), description (optional, details), duedate (optional, YYYY-MM-DD format). For German dates like 'morgen', 'รผbermorgen', calculate from today ({{ $now.toFormat('yyyy-MM-dd') }}). Be concise.\"\n },\n {\n \"role\": \"user\",\n \"content\": \"{{ $json.taskText }}\"\n }\n ],\n \"temperature\": 0.3,\n \"max_tokens\": 150\n}", "options": {} }, "id": "ai-extract-task-1", "name": "AI Extract Task Details", "type": "n8n-nodes-base.httpRequest", "typeVersion": 4.1, "position": [ 1120, 100 ], "credentials": { "httpHeaderAuth": { "id": "openai_api_key", "name": "OpenAI API Key" }, "openAiApi": { "id": "GPzxHwwXxeZg07o5", "name": "OpenAi account" } } }, { "parameters": { "mode": "runOnceForEachItem", "jsCode": "// Parse AI response\nconst aiResponse = $input.item.json.choices[0].message.content;\nlet taskData;\n\ntry {\n // Try to parse as JSON\n taskData = JSON.parse(aiResponse);\n} catch (e) {\n // Fallback to original text\n taskData = {\n title: $input.item.json.taskText.substring(0, 100),\n description: $input.item.json.taskText,\n duedate: null\n };\n}\n\nreturn {\n chatId: $input.item.json.chatId,\n title: taskData.title || 'Untitled Task',\n description: taskData.description || '',\n duedate: taskData.duedate || null\n};" }, "id": "format-task-data-1", "name": "Format Task Data", "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [ 1340, 100 ] }, { "parameters": { "command": "=/home/node/create_card_from_ai.sh \"{{ $json.title }}\" \"{{ $json.description }}\" \"{{ $json.duedate || '' }}\"" }, "id": "create-deck-card-1", "name": "Create Deck Card", "type": "n8n-nodes-base.executeCommand", "typeVersion": 1, "position": [ 1560, 100 ] }, { "parameters": { "mode": "runOnceForEachItem", "jsCode": "// Check if card creation was successful\nconst output = $input.item.json.stdout || '';\nconst error = $input.item.json.stderr || '';\n\nlet success = false;\nlet cardUrl = '';\n\nif (output.includes('Card created') || !error) {\n success = true;\n // Extract card URL if present in output\n const urlMatch = output.match(/https?:\\/\\/[^\\s]+/);\n cardUrl = urlMatch ? urlMatch[0] : '';\n}\n\nconst responseText = success \n ? `โœ… Task added to Nextcloud Deck!\\n\\n๐Ÿ“‹ *${$input.item.json.title}*${$input.item.json.duedate ? '\\n๐Ÿ“… Due: ' + $input.item.json.duedate : ''}${cardUrl ? '\\n๐Ÿ”— ' + cardUrl : ''}`\n : `โŒ Failed to create task.\\n\\nError: ${error}`;\n\nreturn {\n chatId: $input.item.json.chatId,\n text: responseText,\n parseMode: 'Markdown'\n};" }, "id": "format-success-response-1", "name": "Format Success Response", "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [ 1780, 100 ] }, { "parameters": { "respondWith": "json", "responseBody": "={{ JSON.stringify($json) }}", "options": {} }, "id": "respond-result-1", "name": "Respond Result", "type": "n8n-nodes-base.respondToWebhook", "typeVersion": 1, "position": [ 2000, 300 ] }, { "parameters": { "respondWith": "json", "responseBody": "={{ JSON.stringify({\n chatId: $json.chatId,\n text: \"โŒ Please specify a task to add.\\n\\nExample: /deck add Review Q4 reports by Friday\"\n}) }}", "options": {} }, "id": "respond-no-task-1", "name": "Respond No Task", "type": "n8n-nodes-base.respondToWebhook", "typeVersion": 1, "position": [ 1120, 300 ] }, { "parameters": { "respondWith": "json", "responseBody": "={{ JSON.stringify({\n chatId: $json.chatId,\n text: \"๐Ÿ“‹ *Deck Commands*\\n\\n/deck add - Add a task\\n/deck list - List tasks (coming soon)\\n\\nExample:\\n/deck add Review project proposal by tomorrow\"\n}) }}", "options": {} }, "id": "respond-deck-help-1", "name": "Respond Deck Help", "type": "n8n-nodes-base.respondToWebhook", "typeVersion": 1, "position": [ 900, 580 ] }, { "parameters": { "respondWith": "json", "responseBody": "={{ JSON.stringify({\n chatId: $json.chatId,\n text: \"๐Ÿ“‹ List functionality coming soon!\\n\\nFor now, check your Nextcloud Deck directly at:\\nhttps://nextcloud.egonetix.de/apps/deck\"\n}) }}", "options": {} }, "id": "respond-list-placeholder-1", "name": "Respond List (Coming Soon)", "type": "n8n-nodes-base.respondToWebhook", "typeVersion": 1, "position": [ 900, 400 ] } ], "connections": { "Webhook": { "main": [ [ { "node": "Parse Deck Command", "type": "main", "index": 0 } ] ] }, "Parse Deck Command": { "main": [ [ { "node": "Route Deck Action", "type": "main", "index": 0 } ] ] }, "Route Deck Action": { "main": [ [ { "node": "Check Task Text", "type": "main", "index": 0 } ] ] }, "Check Task Text": { "main": [ [ { "node": "AI Extract Task Details", "type": "main", "index": 0 } ], [ { "node": "Respond No Task", "type": "main", "index": 0 } ] ] }, "AI Extract Task Details": { "main": [ [ { "node": "Format Task Data", "type": "main", "index": 0 } ] ] }, "Format Task Data": { "main": [ [ { "node": "Create Deck Card", "type": "main", "index": 0 } ] ] }, "Create Deck Card": { "main": [ [ { "node": "Format Success Response", "type": "main", "index": 0 } ] ] }, "Format Success Response": { "main": [ [ { "node": "Respond Result", "type": "main", "index": 0 } ] ] }, "Respond No Task": { "main": [ [ { "node": "Respond Result", "type": "main", "index": 0 } ] ] }, "Respond Deck Help": { "main": [ [ { "node": "Respond Result", "type": "main", "index": 0 } ] ] }, "Respond List (Coming Soon)": { "main": [ [ { "node": "Respond Result", "type": "main", "index": 0 } ] ] } }, "settings": {}, "staticData": null, "meta": null, "pinData": {}, "triggerCount": 0, "tags": [] }