276 lines
9.2 KiB
JSON
276 lines
9.2 KiB
JSON
{
|
|
"name": "Telegram Assistant - Receiver",
|
|
"nodes": [
|
|
{
|
|
"parameters": {
|
|
"httpMethod": "POST",
|
|
"path": "8f3f59db-aaa5-4762-9416-94be04131fd2",
|
|
"options": {}
|
|
},
|
|
"id": "telegram-trigger-1",
|
|
"name": "Webhook",
|
|
"type": "n8n-nodes-base.webhook",
|
|
"typeVersion": 1,
|
|
"position": [
|
|
240,
|
|
300
|
|
],
|
|
"webhookId": "8f3f59db-aaa5-4762-9416-94be04131fd2"
|
|
},
|
|
{
|
|
"parameters": {
|
|
"conditions": {
|
|
"string": [
|
|
{
|
|
"value1": "={{$json.message?.text || ''}}",
|
|
"operation": "startsWith",
|
|
"value2": "/"
|
|
}
|
|
]
|
|
}
|
|
},
|
|
"id": "check-command-1",
|
|
"name": "Check if Command",
|
|
"type": "n8n-nodes-base.if",
|
|
"typeVersion": 1,
|
|
"position": [
|
|
460,
|
|
300
|
|
]
|
|
},
|
|
{
|
|
"parameters": {
|
|
"chatId": "={{ $json.message.chat.id }}",
|
|
"text": "=Command received: {{ $json.message.text }}\n\nProcessing...",
|
|
"additionalFields": {}
|
|
},
|
|
"id": "send-ack-1",
|
|
"name": "Send Acknowledgment",
|
|
"type": "n8n-nodes-base.telegram",
|
|
"typeVersion": 1,
|
|
"position": [
|
|
680,
|
|
200
|
|
],
|
|
"credentials": {
|
|
"telegramApi": {
|
|
"id": "6Rim8odDFpQoHxCM",
|
|
"name": "mortimer"
|
|
}
|
|
}
|
|
},
|
|
{
|
|
"parameters": {
|
|
"mode": "runOnceForEachItem",
|
|
"jsCode": "// Extract command and parameters\nconst text = $input.item.json.message?.text || '';\nconst chatId = $input.item.json.message?.chat?.id;\nconst messageId = $input.item.json.message?.message_id;\nconst userId = $input.item.json.message?.from?.id;\nconst username = $input.item.json.message?.from?.username || 'unknown';\n\n// Parse command\nconst parts = text.trim().split(/\\s+/);\nconst command = parts[0].toLowerCase();\nconst args = parts.slice(1).join(' ');\n\nreturn {\n command: command,\n args: args,\n chatId: chatId,\n messageId: messageId,\n userId: userId,\n username: username,\n originalText: text\n};"
|
|
},
|
|
"id": "parse-command-1",
|
|
"name": "Parse Command",
|
|
"type": "n8n-nodes-base.code",
|
|
"typeVersion": 2,
|
|
"position": [
|
|
900,
|
|
200
|
|
]
|
|
},
|
|
{
|
|
"parameters": {
|
|
"mode": "runOnceForEachItem",
|
|
"jsCode": "// Extract natural language message\nconst text = $input.item.json.message?.text || '';\nconst chatId = $input.item.json.message?.chat?.id;\nconst messageId = $input.item.json.message?.message_id;\nconst userId = $input.item.json.message?.from?.id;\nconst username = $input.item.json.message?.from?.username || 'unknown';\n\nreturn {\n chatId: chatId,\n messageId: messageId,\n userId: userId,\n username: username,\n originalText: text\n};"
|
|
},
|
|
"id": "parse-natural-language-1",
|
|
"name": "Parse Natural Language",
|
|
"type": "n8n-nodes-base.code",
|
|
"typeVersion": 2,
|
|
"position": [
|
|
680,
|
|
400
|
|
]
|
|
},
|
|
{
|
|
"parameters": {
|
|
"method": "POST",
|
|
"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\": \"Analyze user intent and classify into one of these categories. Return ONLY valid JSON with no additional text:\\n\\n1. 'deck_add' - User wants to create a task/card in Nextcloud Deck\\n Examples: 'add a deck called cleaning', 'create task review reports', 'remind me to call mom tomorrow'\\n Extract: {intent: 'deck_add', task: 'task description', duedate: 'YYYY-MM-DD or null'}\\n\\n2. 'email_search' - User wants to search emails\\n Examples: 'find my train ticket', 'search for invoice', 'show emails from last week'\\n Extract: {intent: 'email_search', query: 'search terms'}\\n\\n3. 'general_chat' - General questions, conversation\\n Examples: 'what's the weather', 'explain quantum physics', 'tell me a joke'\\n Extract: {intent: 'general_chat', question: 'full question'}\\n\\nFor dates like 'today', 'tomorrow', 'next week', calculate from today: {{ $now.toFormat('yyyy-MM-dd') }}.\\nFor German: 'morgen' = tomorrow, 'übermorgen' = day after tomorrow.\\n\\nReturn JSON format: {\\\"intent\\\": \\\"category\\\", ...extracted_data}\"\n },\n {\n \"role\": \"user\",\n \"content\": \"{{ $json.originalText }}\"\n }\n ],\n \"temperature\": 0.3,\n \"max_tokens\": 150\n}",
|
|
"options": {}
|
|
},
|
|
"id": "ai-classify-intent-1",
|
|
"name": "AI Classify Intent",
|
|
"type": "n8n-nodes-base.httpRequest",
|
|
"typeVersion": 3,
|
|
"position": [
|
|
900,
|
|
400
|
|
],
|
|
"credentials": {
|
|
"httpHeaderAuth": {
|
|
"id": "openai_api_key",
|
|
"name": "OpenAI API Key"
|
|
}
|
|
}
|
|
},
|
|
{
|
|
"parameters": {
|
|
"mode": "runOnceForEachItem",
|
|
"jsCode": "// Parse AI classification result\nconst aiResponse = $input.item.json.choices[0].message.content;\nconst chatId = $input.item.json.chatId;\nconst userId = $input.item.json.userId;\nconst username = $input.item.json.username;\nconst originalText = $input.item.json.originalText;\n\nlet classification;\ntry {\n classification = JSON.parse(aiResponse);\n} catch (e) {\n // Fallback to general chat if parsing fails\n classification = {\n intent: 'general_chat',\n question: originalText\n };\n}\n\n// Map intent to command format for router\nlet command, args;\n\nswitch (classification.intent) {\n case 'deck_add':\n command = '/deck';\n args = 'add ' + (classification.task || originalText);\n break;\n case 'email_search':\n command = '/email';\n args = 'search ' + (classification.query || originalText);\n break;\n case 'general_chat':\n default:\n command = '/ask';\n args = classification.question || originalText;\n break;\n}\n\nreturn {\n command: command,\n args: args,\n chatId: chatId,\n userId: userId,\n username: username,\n originalText: originalText,\n classifiedIntent: classification.intent\n};"
|
|
},
|
|
"id": "format-as-command-1",
|
|
"name": "Format as Command",
|
|
"type": "n8n-nodes-base.code",
|
|
"typeVersion": 2,
|
|
"position": [
|
|
1120,
|
|
400
|
|
]
|
|
},
|
|
{
|
|
"parameters": {
|
|
"method": "POST",
|
|
"url": "=https://flow.egonetix.de/webhook/telegram-router-direct",
|
|
"sendBody": true,
|
|
"specifyBody": "json",
|
|
"jsonBody": "={{ JSON.stringify($json) }}",
|
|
"options": {
|
|
"response": {
|
|
"response": {
|
|
"neverError": true
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"id": "call-router-natural-1",
|
|
"name": "Call Router (Natural Language)",
|
|
"type": "n8n-nodes-base.httpRequest",
|
|
"typeVersion": 3,
|
|
"position": [
|
|
1340,
|
|
400
|
|
]
|
|
},
|
|
{
|
|
"parameters": {
|
|
"method": "POST",
|
|
"url": "=https://flow.egonetix.de/webhook/telegram-router-direct",
|
|
"sendBody": true,
|
|
"specifyBody": "json",
|
|
"jsonBody": "={{ JSON.stringify($json) }}",
|
|
"options": {
|
|
"response": {
|
|
"response": {
|
|
"neverError": true
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"id": "call-router-1",
|
|
"name": "Call Router Workflow",
|
|
"type": "n8n-nodes-base.httpRequest",
|
|
"typeVersion": 3,
|
|
"position": [
|
|
1120,
|
|
200
|
|
]
|
|
}
|
|
],
|
|
"connections": {
|
|
"Webhook": {
|
|
"main": [
|
|
[
|
|
{
|
|
"node": "Check if Command",
|
|
"type": "main",
|
|
"index": 0
|
|
}
|
|
]
|
|
]
|
|
},
|
|
"Check if Command": {
|
|
"main": [
|
|
[
|
|
{
|
|
"node": "Send Acknowledgment",
|
|
"type": "main",
|
|
"index": 0
|
|
}
|
|
],
|
|
[
|
|
{
|
|
"node": "Parse Natural Language",
|
|
"type": "main",
|
|
"index": 0
|
|
}
|
|
]
|
|
]
|
|
},
|
|
"Parse Natural Language": {
|
|
"main": [
|
|
[
|
|
{
|
|
"node": "AI Classify Intent",
|
|
"type": "main",
|
|
"index": 0
|
|
}
|
|
]
|
|
]
|
|
},
|
|
"AI Classify Intent": {
|
|
"main": [
|
|
[
|
|
{
|
|
"node": "Format as Command",
|
|
"type": "main",
|
|
"index": 0
|
|
}
|
|
]
|
|
]
|
|
},
|
|
"Format as Command": {
|
|
"main": [
|
|
[
|
|
{
|
|
"node": "Call Router (Natural Language)",
|
|
"type": "main",
|
|
"index": 0
|
|
}
|
|
]
|
|
]
|
|
},
|
|
"Send Acknowledgment": {
|
|
"main": [
|
|
[
|
|
{
|
|
"node": "Parse Command",
|
|
"type": "main",
|
|
"index": 0
|
|
}
|
|
]
|
|
]
|
|
},
|
|
"Parse Command": {
|
|
"main": [
|
|
[
|
|
{
|
|
"node": "Call Router Workflow",
|
|
"type": "main",
|
|
"index": 0
|
|
}
|
|
]
|
|
]
|
|
}
|
|
},
|
|
"settings": {}
|
|
}
|