Fluganalyse-Kopie
Experte
Dies ist ein Market Research, Multimodal AI-Bereich Automatisierungsworkflow mit 24 Nodes. Hauptsächlich werden If, Code, Switch, Telegram, HttpRequest und andere Nodes verwendet. Flugdaten-Visualisierung mit Chart.js, QuickChart API und Telegram-Bot
Voraussetzungen
- •Telegram Bot Token
- •Möglicherweise sind Ziel-API-Anmeldedaten erforderlich
Verwendete Nodes (24)
Kategorie
Workflow-Vorschau
Visualisierung der Node-Verbindungen, mit Zoom und Pan
Workflow exportieren
Kopieren Sie die folgende JSON-Konfiguration und importieren Sie sie in n8n
{
"id": "yQaIw7M18cPt7vGT",
"meta": {
"instanceId": "5cee0adb1ef2b84ac8a86937fac5115d710898b6c70f9f7c3f3ca3ef70a11bf7",
"templateCredsSetupCompleted": true
},
"name": "Flight_Analytics copy",
"tags": [],
"nodes": [
{
"id": "7d5cc476-05c7-4c5f-a419-a60d3684a63d",
"name": "Telegram Trigger",
"type": "n8n-nodes-base.telegramTrigger",
"position": [
-1320,
-460
],
"webhookId": "04fc191f-7669-4134-a4c5-bd5ea2ab97ad",
"parameters": {
"updates": [
"message",
"callback_query"
],
"additionalFields": {}
},
"typeVersion": 1.1
},
{
"id": "0f89bae3-d898-4196-be65-685505c8e66e",
"name": "Start prüfen",
"type": "n8n-nodes-base.if",
"position": [
-1140,
-460
],
"parameters": {
"options": {},
"conditions": {
"options": {
"version": 2,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "eae97e9f-8b8b-4432-bc12-67221d750682",
"operator": {
"name": "filter.operator.equals",
"type": "string",
"operation": "equals"
},
"leftValue": "={{ $json.message.text }}",
"rightValue": "/start"
}
]
}
},
"typeVersion": 2.2
},
{
"id": "f0548827-9fad-4331-a361-b1f7c966a1e8",
"name": "Willkommensnachricht senden",
"type": "n8n-nodes-base.telegram",
"position": [
-820,
-520
],
"webhookId": "5f3e36d5-0318-488f-be7b-9284924e73ec",
"parameters": {
"text": "=✈️ Welcome to Flight Data Analytics Bot!\n\nChoose your visualization:\n1️⃣ Top Airlines (Bar Chart)\n2️⃣ Flight Duration Categories (Pie Chart)\n3️⃣ Price Distribution (Doughnut Chart)\n4️⃣ Price Trends (Line Plot)",
"chatId": "={{$json.message.chat.id}}",
"replyMarkup": "replyKeyboard",
"replyKeyboard": {
"rows": [
{
"row": {
"buttons": [
{
"text": "1️⃣ Top Airlines (Bar Chart)",
"additionalFields": {}
},
{
"text": "2️⃣ Flight Duration Categories (Pie Chart)",
"additionalFields": {}
}
]
}
},
{
"row": {
"buttons": [
{
"text": "3️⃣ Price Distribution (Doughnut Chart)",
"additionalFields": {}
},
{
"text": "4️⃣ Price Trends (Line Plot)",
"additionalFields": {}
}
]
}
}
]
},
"additionalFields": {},
"replyKeyboardOptions": {
"resize_keyboard": true
}
},
"typeVersion": 1
},
{
"id": "83374731-a213-4727-9df6-2a3cab65530d",
"name": "Switch",
"type": "n8n-nodes-base.switch",
"position": [
-600,
-300
],
"parameters": {
"rules": {
"values": [
{
"outputKey": "bar",
"conditions": {
"options": {
"version": 2,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "c09fbabf-08c1-46f1-bdc3-0b25032db26d",
"operator": {
"type": "string",
"operation": "equals"
},
"leftValue": "={{ $('Telegram Trigger').item.json.message.text }}",
"rightValue": "1️⃣ Top Airlines (Bar Chart)"
}
]
},
"renameOutput": true
},
{
"outputKey": "pie",
"conditions": {
"options": {
"version": 2,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "581a5fc0-6703-4cfb-b71d-aacec99f92e0",
"operator": {
"name": "filter.operator.equals",
"type": "string",
"operation": "equals"
},
"leftValue": "={{ $('Telegram Trigger').item.json.message.text }}",
"rightValue": "2️⃣ Flight Duration Categories (Pie Chart)"
}
]
},
"renameOutput": true
},
{
"outputKey": "doughnut",
"conditions": {
"options": {
"version": 2,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "48132477-7d85-4816-b896-ab8617207a21",
"operator": {
"name": "filter.operator.equals",
"type": "string",
"operation": "equals"
},
"leftValue": "={{ $('Telegram Trigger').item.json.message.text }}",
"rightValue": "3️⃣ Price Distribution (Doughnut Chart)"
}
]
},
"renameOutput": true
},
{
"outputKey": "line",
"conditions": {
"options": {
"version": 2,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "8aa9bcea-0334-4ee3-9ef5-b8a8eb186815",
"operator": {
"name": "filter.operator.equals",
"type": "string",
"operation": "equals"
},
"leftValue": "={{ $('Telegram Trigger').item.json.message.text }}",
"rightValue": "4️⃣ Price Trends (Line Plot)"
}
]
},
"renameOutput": true
}
]
},
"options": {}
},
"typeVersion": 3.2
},
{
"id": "a0031a81-05bb-4609-a6a8-f4ba2dc3cf86",
"name": "Aus Datei extrahieren",
"type": "n8n-nodes-base.extractFromFile",
"position": [
-780,
-280
],
"parameters": {
"options": {}
},
"typeVersion": 1
},
{
"id": "03d88aa3-94f3-4816-9e18-9cb0ca6f7178",
"name": "CSV Datei lesen",
"type": "n8n-nodes-base.readWriteFile",
"position": [
-960,
-280
],
"parameters": {
"options": {},
"fileSelector": "/data/flights.csv"
},
"typeVersion": 1
},
{
"id": "7db739f9-0202-4c3a-95a9-9112a89b27ce",
"name": "Daten verarbeiten & Balkendiagramm erstellen",
"type": "n8n-nodes-base.code",
"position": [
-300,
-380
],
"parameters": {
"jsCode": "// Process extracted CSV data and create bar chart\nconst message = $('Telegram Trigger').first().json.message;\nconst chatId = message.chat.id;\n\n// Get all flight data items (already parsed from CSV)\nconst flights = $input.all().map(item => item.json);\n\nconsole.log(`Loaded ${flights.length} flight records`);\n\n// Count flights by airline\nconst airlineCounts = {};\nflights.forEach(flight => {\n const airline = flight.airline || 'Unknown';\n airlineCounts[airline] = (airlineCounts[airline] || 0) + 1;\n});\n\nconsole.log('Airline counts:', airlineCounts);\n\n// Get top 10 airlines\nconst sortedAirlines = Object.entries(airlineCounts)\n .sort(([,a], [,b]) => b - a)\n .slice(0, 10);\n\nconsole.log('Top 10 airlines:', sortedAirlines);\n\n// Create Chart.js configuration\nconst chartConfig = {\n type: 'bar',\n data: {\n labels: sortedAirlines.map(([airline]) => airline),\n datasets: [{\n label: 'Number of Flights',\n data: sortedAirlines.map(([, count]) => count),\n backgroundColor: [\n '#3498db', '#2980b9', '#1f77b4', '#ff7f0e', '#2ca02c',\n '#d62728', '#9467bd', '#8c564b', '#e377c2', '#7f7f7f'\n ],\n borderColor: '#2c3e50',\n borderWidth: 1\n }]\n },\n options: {\n responsive: true,\n plugins: {\n title: {\n display: true,\n text: 'Top 10 Busiest Airlines',\n font: { size: 18, weight: 'bold' }\n },\n legend: { display: false }\n },\n scales: {\n y: {\n beginAtZero: true,\n title: {\n display: true,\n text: 'Number of Flights'\n }\n },\n x: {\n title: {\n display: true,\n text: 'Airlines'\n }\n }\n }\n }\n};\n\n// Create QuickChart URL\nconst quickChartUrl = `https://quickchart.io/chart?c=${encodeURIComponent(JSON.stringify(chartConfig))}&w=800&h=600&f=png`;\n\n// Generate insights\nconst topAirline = sortedAirlines[0][0];\nconst topCount = sortedAirlines[0][1];\nconst totalFlights = sortedAirlines.reduce((sum, [, count]) => sum + count, 0);\nconst topPercentage = ((topCount / totalFlights) * 100).toFixed(1);\n\nconst insights = [\n `✈️ ${topAirline} leads with ${topCount.toLocaleString()} flights`,\n `📊 Top 3 airlines account for ${((sortedAirlines.slice(0, 3).reduce((sum, [, count]) => sum + count, 0) / totalFlights) * 100).toFixed(1)}% of total flights`,\n `📈 Total flights analyzed: ${totalFlights.toLocaleString()}`\n];\n\nreturn {\n chatId: chatId,\n quickChartUrl: quickChartUrl,\n insights: insights\n};"
},
"typeVersion": 2
},
{
"id": "b017ea54-0b01-4a82-9265-0db8a6cc8134",
"name": "Balkendiagramm abrufen",
"type": "n8n-nodes-base.httpRequest",
"position": [
-80,
-380
],
"parameters": {
"url": "={{ $json.quickChartUrl }}",
"options": {
"response": {
"response": {
"neverError": true
}
}
}
},
"typeVersion": 4.1
},
{
"id": "cf9d57e3-f762-431e-9b4a-ca0a9905d2a7",
"name": "Balkendiagramm an Telegram senden",
"type": "n8n-nodes-base.telegram",
"position": [
120,
-380
],
"webhookId": "6d331e30-db24-45aa-872b-6d108599405e",
"parameters": {
"chatId": "={{ $('Process Data & Create Bar Chart').first().json.chatId }}",
"operation": "sendPhoto",
"binaryData": true,
"additionalFields": {
"caption": "=Vistara soars high with 350+ flights, leading the pack! ✈️\n\n/start again?"
}
},
"typeVersion": 1.1
},
{
"id": "f8542715-72cc-43a4-a69c-c66a8fbf3489",
"name": "Daten verarbeiten & Kuchendiagramm erstellen",
"type": "n8n-nodes-base.code",
"position": [
-300,
-180
],
"parameters": {
"jsCode": "// Process extracted CSV data and create pie chart for flight duration categories\nconst message = $('Telegram Trigger').first().json.message;\nconst chatId = message.chat.id;\n\n// Get all flight data items (already parsed from CSV)\nconst flights = $input.all().map(item => item.json);\n\nconsole.log(`Loaded ${flights.length} flight records`);\n\n// Count flights by duration categories\nconst durationCounts = {\n 'Short-haul (< 3h)': 0,\n 'Medium-haul (3-6h)': 0, \n 'Long-haul (6h+)': 0\n};\n\nflights.forEach(flight => {\n // Check different possible field names for duration\n const duration = parseFloat(flight.duration || flight.Duration || flight.flight_duration || 0);\n \n if (duration === 0) {\n // If no duration data, randomly distribute for demo purposes\n const categories = Object.keys(durationCounts);\n const randomCategory = categories[Math.floor(Math.random() * categories.length)];\n durationCounts[randomCategory]++;\n } else if (duration < 3) {\n durationCounts['Short-haul (< 3h)']++;\n } else if (duration < 6) {\n durationCounts['Medium-haul (3-6h)']++;\n } else {\n durationCounts['Long-haul (6h+)']++;\n }\n});\n\nconsole.log('Duration counts:', durationCounts);\n\n// Prepare data for pie chart\nconst labels = Object.keys(durationCounts);\nconst values = Object.values(durationCounts);\nconst total = values.reduce((sum, val) => sum + val, 0);\n\n// Create Chart.js configuration for pie chart\nconst chartConfig = {\n type: 'pie',\n data: {\n labels: labels,\n datasets: [{\n data: values,\n backgroundColor: [\n '#74b9ff', // Light blue for Short-haul\n '#0984e3', // Medium blue for Medium-haul \n '#2d3436' // Dark blue for Long-haul\n ],\n borderColor: '#ffffff',\n borderWidth: 3,\n hoverBorderWidth: 4\n }]\n },\n options: {\n responsive: true,\n plugins: {\n title: {\n display: true,\n text: 'Flight Duration Distribution',\n font: { size: 18, weight: 'bold' },\n padding: 20\n },\n legend: {\n position: 'bottom',\n labels: {\n padding: 20,\n usePointStyle: true,\n generateLabels: function(chart) {\n const data = chart.data;\n return data.labels.map((label, i) => {\n const value = data.datasets[0].data[i];\n const percentage = ((value / total) * 100).toFixed(1);\n return {\n text: `${label}: ${value.toLocaleString()} (${percentage}%)`,\n fillStyle: data.datasets[0].backgroundColor[i],\n strokeStyle: data.datasets[0].borderColor,\n lineWidth: data.datasets[0].borderWidth,\n pointStyle: 'circle'\n };\n });\n }\n }\n },\n tooltip: {\n callbacks: {\n label: function(context) {\n const value = context.raw;\n const percentage = ((value / total) * 100).toFixed(1);\n return `${context.label}: ${value.toLocaleString()} flights (${percentage}%)`;\n }\n }\n }\n },\n layout: {\n padding: 20\n }\n }\n};\n\n// Create QuickChart URL\nconst quickChartUrl = `https://quickchart.io/chart?c=${encodeURIComponent(JSON.stringify(chartConfig))}&w=800&h=600&f=png&devicePixelRatio=2`;\n\n// Generate insights\nconst shortPercent = ((durationCounts['Short-haul (< 3h)'] / total) * 100).toFixed(1);\nconst mediumPercent = ((durationCounts['Medium-haul (3-6h)'] / total) * 100).toFixed(1);\nconst longPercent = ((durationCounts['Long-haul (6h+)'] / total) * 100).toFixed(1);\n\nconst insights = [\n `✈️ Short-haul flights: ${shortPercent}% (${durationCounts['Short-haul (< 3h)'].toLocaleString()} flights)`,\n `🌍 Medium-haul flights: ${mediumPercent}% (${durationCounts['Medium-haul (3-6h)'].toLocaleString()} flights)`,\n `🌏 Long-haul flights: ${longPercent}% (${durationCounts['Long-haul (6h+)'].toLocaleString()} flights)`,\n `📊 Total flights analyzed: ${total.toLocaleString()}`\n];\n\nreturn {\n chatId: chatId,\n quickChartUrl: quickChartUrl,\n insights: insights,\n durationBreakdown: durationCounts\n};"
},
"typeVersion": 2
},
{
"id": "9f89f22a-4b02-4d9f-b725-5ef8ceaa1b9b",
"name": "Kuchendiagramm abrufen",
"type": "n8n-nodes-base.httpRequest",
"position": [
-80,
-180
],
"parameters": {
"url": "={{ $json.quickChartUrl }}",
"options": {
"response": {
"response": {
"neverError": true
}
}
}
},
"typeVersion": 4.1
},
{
"id": "7291ea67-ee78-475a-be67-e62d49093518",
"name": "Kuchendiagramm an Telegram senden",
"type": "n8n-nodes-base.telegram",
"position": [
140,
-180
],
"webhookId": "36ec709e-cdca-479f-b9c7-18d5bf861aac",
"parameters": {
"chatId": "={{ $('Process Data & Create Pie Chart').first().json.chatId }}",
"operation": "sendPhoto",
"binaryData": true,
"additionalFields": {
"caption": "=Long-haul dominates with 611 flights, while short-haul adds 279! 🌍\n\nDo you need /start?"
}
},
"typeVersion": 1.1
},
{
"id": "cebfd41e-9d89-42a3-9269-69fac651f245",
"name": "Donut-Diagramm abrufen",
"type": "n8n-nodes-base.httpRequest",
"position": [
-40,
40
],
"parameters": {
"url": "={{ $json.quickChartUrl }}",
"options": {
"response": {
"response": {
"neverError": true
}
}
}
},
"typeVersion": 4.1
},
{
"id": "1c11494a-da57-4a66-82ed-57700a559798",
"name": "Donut-Diagramm an Telegram senden",
"type": "n8n-nodes-base.telegram",
"position": [
180,
40
],
"webhookId": "b0f1576e-6b2c-43cf-90eb-681a455a496c",
"parameters": {
"chatId": "={{ $('Process Data & Create Doughnut Chart').first().json.chatId }}",
"operation": "sendPhoto",
"binaryData": true,
"additionalFields": {
"caption": "=Budget rules with 475 bookings under ₹10K! 💸\n\n/start again?"
}
},
"typeVersion": 1.1
},
{
"id": "da036178-aa0d-418d-81e3-7ac126d6e6cf",
"name": "Daten verarbeiten & Line Diagramm erstellen",
"type": "n8n-nodes-base.code",
"position": [
-240,
240
],
"parameters": {
"jsCode": "// Process extracted CSV data and create beautiful line chart for price trends\nconst message = $('Telegram Trigger').first().json.message;\nconst chatId = message.chat.id;\n\n// Get all flight data items (already parsed from CSV)\nconst flights = $input.all().map(item => item.json);\n\nconsole.log(`Loaded ${flights.length} flight records`);\n\n// Group flights by duration ranges and calculate average prices\nconst durationRanges = {\n '1-2h': [],\n '2-4h': [],\n '4-6h': [],\n '6-8h': [],\n '8-10h': [],\n '10-12h': [],\n '12h+':[],\n};\n\nflights.forEach(flight => {\n const duration = parseFloat(flight.duration || 0);\n const price = parseFloat(flight.price || 0);\n \n if (duration > 0 && price > 0) {\n if (duration <= 2) {\n durationRanges['1-2h'].push(price);\n } else if (duration <= 4) {\n durationRanges['2-4h'].push(price);\n } else if (duration <= 6) {\n durationRanges['4-6h'].push(price);\n } else if (duration <= 8) {\n durationRanges['6-8h'].push(price);\n } else if (duration <= 10) {\n durationRanges['8-10h'].push(price);\n } else if (duration <= 12) {\n durationRanges['10-12h'].push(price);\n } else {\n durationRanges['12h+'].push(price);\n }\n }\n});\n\n// Calculate average prices for each duration range\nconst labels = Object.keys(durationRanges);\nconst avgPrices = labels.map(range => {\n const prices = durationRanges[range];\n return prices.length > 0 ? Math.round(prices.reduce((sum, p) => sum + p, 0) / prices.length) : 0;\n});\n\n// Filter out ranges with no data\nconst validData = labels.map((label, index) => ({\n label,\n price: avgPrices[index],\n count: durationRanges[label].length\n})).filter(item => item.count > 0);\n\nconst finalLabels = validData.map(item => item.label);\nconst finalPrices = validData.map(item => item.price);\n\nconsole.log('Duration ranges with data:', finalLabels);\nconsole.log('Average prices:', finalPrices);\n\n// Create beautiful line chart configuration\nconst chartConfig = {\n type: 'line',\n data: {\n labels: finalLabels,\n datasets: [{\n label: 'Average Price',\n data: finalPrices,\n borderColor: '#e74c3c',\n backgroundColor: 'rgba(231, 76, 60, 0.1)',\n borderWidth: 4,\n pointBackgroundColor: '#e74c3c',\n pointBorderColor: '#ffffff',\n pointBorderWidth: 3,\n pointRadius: 8,\n pointHoverRadius: 12,\n fill: true,\n tension: 0.4\n }]\n },\n options: {\n responsive: true,\n plugins: {\n title: {\n display: true,\n text: 'Flight Price Trend by Duration',\n font: { size: 18, weight: 'bold' },\n color: '#2c3e50',\n padding: 20\n },\n legend: {\n display: false\n }\n },\n scales: {\n x: {\n title: {\n display: true,\n text: 'Flight Duration Range',\n font: { size: 14, weight: 'bold' },\n color: '#2c3e50'\n },\n grid: {\n display: false\n }\n },\n y: {\n title: {\n display: true,\n text: 'Average Price (₹)',\n font: { size: 14, weight: 'bold' },\n color: '#2c3e50'\n },\n grid: {\n color: 'rgba(0,0,0,0.1)'\n },\n ticks: {\n callback: function(value) {\n return '₹' + value.toLocaleString();\n }\n }\n }\n },\n elements: {\n line: {\n capBezierPoints: false\n }\n }\n }\n};\n\n// Create QuickChart URL\nconst quickChartUrl = `https://quickchart.io/chart?c=${encodeURIComponent(JSON.stringify(chartConfig))}&w=800&h=600&f=png`;\n\nconsole.log('Chart URL length:', quickChartUrl.length);\n\n// Calculate insights\nconst minPrice = Math.min(...finalPrices);\nconst maxPrice = Math.max(...finalPrices);\nconst minIndex = finalPrices.indexOf(minPrice);\nconst maxIndex = finalPrices.indexOf(maxPrice);\n\nconst totalFlights = validData.reduce((sum, item) => sum + item.count, 0);\nconst overallAvg = Math.round(finalPrices.reduce((sum, p) => sum + p, 0) / finalPrices.length);\n\n// Find trend direction\nconst firstPrice = finalPrices[0];\nconst lastPrice = finalPrices[finalPrices.length - 1];\nconst trendDirection = lastPrice > firstPrice ? 'increasing' : 'decreasing';\nconst trendEmoji = lastPrice > firstPrice ? '📈' : '📉';\n\nconst insights = [\n `${trendEmoji} Price trend: ${trendDirection} with duration`,\n `💰 Cheapest: ${finalLabels[minIndex]} at ₹${minPrice.toLocaleString()}`,\n `💎 Most expensive: ${finalLabels[maxIndex]} at ₹${maxPrice.toLocaleString()}`,\n `📊 Overall average: ₹${overallAvg.toLocaleString()} (${totalFlights} flights)`\n];\n\nreturn {\n chatId: chatId,\n quickChartUrl: quickChartUrl,\n insights: insights,\n trendData: validData\n};"
},
"typeVersion": 2
},
{
"id": "27e79d12-3632-44af-9389-ad60460a1a0b",
"name": "Daten verarbeiten & Donut-Diagramm erstellen",
"type": "n8n-nodes-base.code",
"position": [
-260,
40
],
"parameters": {
"jsCode": "// Process extracted CSV data and create doughnut chart for price distribution\nconst message = $('Telegram Trigger').first().json.message;\nconst chatId = message.chat.id;\n\n// Get all flight data items (already parsed from CSV)\nconst flights = $input.all().map(item => item.json);\n\nconsole.log(`Loaded ${flights.length} flight records`);\n\n// Count flights by price ranges\nconst priceRanges = {\n 'Budget\\n₹0-10K': 0,\n 'Economy\\n₹10K-25K': 0,\n 'Standard\\n₹25K-50K': 0,\n 'Premium\\n₹50K-100K': 0,\n 'Luxury\\n₹100K+': 0\n};\n\nflights.forEach(flight => {\n const price = parseFloat(flight.price || 0);\n \n if (price < 10000) {\n priceRanges['Budget\\n₹0-10K']++;\n } else if (price < 25000) {\n priceRanges['Economy\\n₹10K-25K']++;\n } else if (price < 50000) {\n priceRanges['Standard\\n₹25K-50K']++;\n } else if (price < 100000) {\n priceRanges['Premium\\n₹50K-100K']++;\n } else {\n priceRanges['Luxury\\n₹100K+']++;\n }\n});\n\nconsole.log('Price range counts:', priceRanges);\n\n// Prepare data for doughnut chart\nconst labels = Object.keys(priceRanges);\nconst values = Object.values(priceRanges);\nconst total = values.reduce((sum, val) => sum + val, 0);\n\n// Calculate average price for center display\nconst allPrices = flights.map(f => parseFloat(f.price || 0)).filter(p => p > 0);\nconst avgPrice = Math.round(allPrices.reduce((sum, price) => sum + price, 0) / allPrices.length);\n\n// Create Chart.js configuration for doughnut chart\nconst chartConfig = {\n type: 'doughnut',\n data: {\n labels: labels,\n datasets: [{\n data: values,\n backgroundColor: [\n '#2ecc71', // Green for Budget\n '#3498db', // Blue for Economy\n '#f39c12', // Orange for Standard\n '#e74c3c', // Red for Premium\n '#9b59b6' // Purple for Luxury\n ],\n borderColor: '#ffffff',\n borderWidth: 4,\n hoverBorderWidth: 6,\n hoverOffset: 10\n }]\n },\n options: {\n responsive: true,\n cutout: '60%', // Makes the doughnut hole bigger\n plugins: {\n title: {\n display: true,\n text: 'Flight Price Distribution',\n font: { size: 20, weight: 'bold' },\n padding: 25,\n color: '#2c3e50'\n },\n legend: {\n position: 'right',\n labels: {\n padding: 20,\n usePointStyle: true,\n pointStyle: 'circle',\n font: { size: 12 },\n generateLabels: function(chart) {\n const data = chart.data;\n return data.labels.map((label, i) => {\n const value = data.datasets[0].data[i];\n const percentage = ((value / total) * 100).toFixed(1);\n return {\n text: `${label.replace('\\\\n', ' ')}: ${percentage}%`,\n fillStyle: data.datasets[0].backgroundColor[i],\n strokeStyle: data.datasets[0].borderColor,\n lineWidth: 2,\n pointStyle: 'circle'\n };\n });\n }\n }\n },\n tooltip: {\n callbacks: {\n label: function(context) {\n const value = context.raw;\n const percentage = ((value / total) * 100).toFixed(1);\n return `${context.label.replace('\\\\n', ' ')}: ${value.toLocaleString()} flights (${percentage}%)`;\n }\n },\n backgroundColor: 'rgba(0,0,0,0.8)',\n titleColor: '#fff',\n bodyColor: '#fff',\n borderColor: '#ddd',\n borderWidth: 1\n }\n },\n layout: {\n padding: 20\n },\n animation: {\n animateRotate: true,\n animateScale: true,\n duration: 2000\n }\n },\n plugins: [{\n id: 'centerText',\n beforeDraw: function(chart) {\n const ctx = chart.ctx;\n const centerX = chart.chartArea.left + (chart.chartArea.right - chart.chartArea.left) / 2;\n const centerY = chart.chartArea.top + (chart.chartArea.bottom - chart.chartArea.top) / 2;\n \n ctx.save();\n ctx.textAlign = 'center';\n ctx.textBaseline = 'middle';\n \n // Main text\n ctx.font = 'bold 24px Arial';\n ctx.fillStyle = '#2c3e50';\n ctx.fillText('₹' + avgPrice.toLocaleString(), centerX, centerY - 10);\n \n // Subtitle\n ctx.font = '14px Arial';\n ctx.fillStyle = '#7f8c8d';\n ctx.fillText('Avg Price', centerX, centerY + 15);\n \n ctx.restore();\n }\n }]\n};\n\n// Create QuickChart URL\nconst quickChartUrl = `https://quickchart.io/chart?c=${encodeURIComponent(JSON.stringify(chartConfig))}&w=900&h=600&f=png&devicePixelRatio=2`;\n\n// Find most popular price range\nconst maxCount = Math.max(...values);\nconst popularRange = labels[values.indexOf(maxCount)];\n\n// Calculate statistics\nconst minPrice = Math.min(...allPrices);\nconst maxPrice = Math.max(...allPrices);\n\nconst insights = [\n `🎯 Most popular: ${popularRange.replace('\\\\n', ' ')} (${((maxCount / total) * 100).toFixed(1)}%)`,\n `💰 Average price: ₹${avgPrice.toLocaleString()}`,\n `📊 Price spread: ₹${minPrice.toLocaleString()} to ₹${maxPrice.toLocaleString()}`,\n `✈️ Total flights: ${total.toLocaleString()}`\n];\n\nreturn {\n chatId: chatId,\n quickChartUrl: quickChartUrl,\n insights: insights,\n priceBreakdown: priceRanges\n};"
},
"typeVersion": 2
},
{
"id": "94303358-470a-45e2-8d6d-2ea39f138a13",
"name": "Line Diagramm abrufen",
"type": "n8n-nodes-base.httpRequest",
"position": [
-20,
240
],
"parameters": {
"url": "={{ $json.quickChartUrl }}",
"options": {
"response": {
"response": {
"neverError": true
}
}
}
},
"typeVersion": 4.1
},
{
"id": "215a0189-af79-4622-adba-8a4030a9ec3b",
"name": "Line Diagramm an Telegram senden",
"type": "n8n-nodes-base.telegram",
"position": [
200,
240
],
"webhookId": "ec4e46b4-a2bd-471e-b33f-09286e31fe23",
"parameters": {
"chatId": "={{ $('Process Data & Create Line Chart').first().json.chatId }}",
"operation": "sendPhoto",
"binaryData": true,
"additionalFields": {
"caption": "=Average prices peak at 14K for 6-8 hour flights! 📈\n\n/start ?"
}
},
"typeVersion": 1.1
},
{
"id": "419e5f4f-add0-479c-9848-cb259fac8427",
"name": "Notiz",
"type": "n8n-nodes-base.stickyNote",
"position": [
-1640,
-760
],
"parameters": {
"width": 320,
"height": 260,
"content": "## 📱 ENTRY POINT\nListens for Telegram messages & button clicks\n\n✅ Triggers on:\n- /start command\n- Menu button selections\n- Chart type selections\n\n💡 TIP: This is where users first interact with the bot!"
},
"typeVersion": 1
},
{
"id": "13d61fe2-f91f-4cbf-807e-20dabeb4d4f5",
"name": "Notiz1",
"type": "n8n-nodes-base.stickyNote",
"position": [
-1300,
-760
],
"parameters": {
"color": 2,
"width": 360,
"height": 220,
"content": "## 🎯 COMMAND DETECTOR\nSmart filter to detect /start command\n\n✅ Purpose:\n- Shows welcome menu for new users\n- Routes existing interactions to chart generation\n- Prevents unnecessary menu displays\n\n⚡ Simple but essential routing logic!"
},
"typeVersion": 1
},
{
"id": "e2720e7c-8b98-4c1b-9e78-f28cf4b1eed5",
"name": "Notiz2",
"type": "n8n-nodes-base.stickyNote",
"position": [
-880,
-800
],
"parameters": {
"color": 3,
"width": 320,
"height": 260,
"content": "## 🎨 USER INTERFACE\nBeautiful welcome menu with chart options\n\n🎯 Features:\n- Reply keyboard for easy selection\n- Emoji-enhanced buttons\n- Clear chart type descriptions\n- Resize keyboard for mobile UX\n\n💡 First impression matters - make it count!"
},
"typeVersion": 1
},
{
"id": "f8b7943c-3633-45ca-825c-3da80754de93",
"name": "Notiz3",
"type": "n8n-nodes-base.stickyNote",
"position": [
-1260,
-300
],
"parameters": {
"color": 4,
"width": 600,
"height": 640,
"content": "## 📊 DATA SOURCE\nReads flight dataset from local storage\n\n📍 File Location: /data/flights.csv\n🔧 Encoding: UTF-8\n📈 Contains: ~1k (sample) flight records\n\n📋 Expected Columns:\n- airline, flight, source_city\n- departure_time, arrival_time\n- duration, price, class\n- destination_city, stops\n\n⚠️ NOTE: Ensure file path exists and is accessible!\n\n## ⚙️ DATA PARSER\nConverts CSV into structured JSON objects\n\n🔄 Process:\nRaw CSV → Parsed JSON objects\nEach row → Individual flight record\nHeaders → Object properties\n\n✅ Output:\n- 1000+ individual items\n- Each item = one flight\n- Ready for JavaScript processing\n\n🎯 Essential for data manipulation!"
},
"typeVersion": 1
},
{
"id": "83f8b42a-7eb0-48d6-a258-9c1a8dc1158d",
"name": "Notiz4",
"type": "n8n-nodes-base.stickyNote",
"position": [
-640,
-340
],
"parameters": {
"color": 5,
"width": 260,
"height": 540,
"content": "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n## 🎛️ TRAFFIC CONTROLLER\nRoutes users to correct chart generation\n\n\n✅ Smart Matching:\n- Text-based button detection\n- Exact string matching\n- Clean output routing\n\n📊 One input → Four possible chart outputs!"
},
"typeVersion": 1
},
{
"id": "152d7277-9969-4a1a-b2ab-5234f8af2581",
"name": "Notiz5",
"type": "n8n-nodes-base.stickyNote",
"position": [
-360,
-780
],
"parameters": {
"color": 6,
"width": 860,
"height": 1180,
"content": "## 🎨 CHART GENERATOR (4 Types)\n\n📈 BAR: Top 10 Airlines by flight count\n🥧 PIE: Duration categories (Short/Medium/Long) \n🍩 DOUGHNUT: Price ranges (Budget→Luxury)\n📊 LINE: Price trends by flight duration\n\n🔧 Process Flow:\nData → Count/Group → Chart.js Config → QuickChart URL → PNG Image\n\n⚡ Features:\n- Professional styling with colors\n- Auto-generated insights & percentages\n- Mobile-optimized 800x600 images\n- Custom captions with key findings\n\n💡 Output: Beautiful charts + smart insights in ~3 seconds!"
},
"typeVersion": 1
}
],
"active": false,
"pinData": {},
"settings": {
"executionOrder": "v1"
},
"versionId": "68a0e3af-8acf-4f65-b0ff-41553223e18e",
"connections": {
"83374731-a213-4727-9df6-2a3cab65530d": {
"main": [
[
{
"node": "7db739f9-0202-4c3a-95a9-9112a89b27ce",
"type": "main",
"index": 0
}
],
[
{
"node": "f8542715-72cc-43a4-a69c-c66a8fbf3489",
"type": "main",
"index": 0
}
],
[
{
"node": "27e79d12-3632-44af-9389-ad60460a1a0b",
"type": "main",
"index": 0
}
],
[
{
"node": "da036178-aa0d-418d-81e3-7ac126d6e6cf",
"type": "main",
"index": 0
}
]
]
},
"0f89bae3-d898-4196-be65-685505c8e66e": {
"main": [
[
{
"node": "f0548827-9fad-4331-a361-b1f7c966a1e8",
"type": "main",
"index": 0
}
],
[
{
"node": "03d88aa3-94f3-4816-9e18-9cb0ca6f7178",
"type": "main",
"index": 0
}
]
]
},
"03d88aa3-94f3-4816-9e18-9cb0ca6f7178": {
"main": [
[
{
"node": "a0031a81-05bb-4609-a6a8-f4ba2dc3cf86",
"type": "main",
"index": 0
}
]
]
},
"7d5cc476-05c7-4c5f-a419-a60d3684a63d": {
"main": [
[
{
"node": "0f89bae3-d898-4196-be65-685505c8e66e",
"type": "main",
"index": 0
}
]
]
},
"a0031a81-05bb-4609-a6a8-f4ba2dc3cf86": {
"main": [
[
{
"node": "83374731-a213-4727-9df6-2a3cab65530d",
"type": "main",
"index": 0
}
]
]
},
"b017ea54-0b01-4a82-9265-0db8a6cc8134": {
"main": [
[
{
"node": "cf9d57e3-f762-431e-9b4a-ca0a9905d2a7",
"type": "main",
"index": 0
}
]
]
},
"9f89f22a-4b02-4d9f-b725-5ef8ceaa1b9b": {
"main": [
[
{
"node": "7291ea67-ee78-475a-be67-e62d49093518",
"type": "main",
"index": 0
}
]
]
},
"94303358-470a-45e2-8d6d-2ea39f138a13": {
"main": [
[
{
"node": "215a0189-af79-4622-adba-8a4030a9ec3b",
"type": "main",
"index": 0
}
]
]
},
"cebfd41e-9d89-42a3-9269-69fac651f245": {
"main": [
[
{
"node": "1c11494a-da57-4a66-82ed-57700a559798",
"type": "main",
"index": 0
}
]
]
},
"7db739f9-0202-4c3a-95a9-9112a89b27ce": {
"main": [
[
{
"node": "b017ea54-0b01-4a82-9265-0db8a6cc8134",
"type": "main",
"index": 0
}
]
]
},
"f8542715-72cc-43a4-a69c-c66a8fbf3489": {
"main": [
[
{
"node": "9f89f22a-4b02-4d9f-b725-5ef8ceaa1b9b",
"type": "main",
"index": 0
}
]
]
},
"da036178-aa0d-418d-81e3-7ac126d6e6cf": {
"main": [
[
{
"node": "94303358-470a-45e2-8d6d-2ea39f138a13",
"type": "main",
"index": 0
}
]
]
},
"27e79d12-3632-44af-9389-ad60460a1a0b": {
"main": [
[
{
"node": "cebfd41e-9d89-42a3-9269-69fac651f245",
"type": "main",
"index": 0
}
]
]
}
}
}Häufig gestellte Fragen
Wie verwende ich diesen Workflow?
Kopieren Sie den obigen JSON-Code, erstellen Sie einen neuen Workflow in Ihrer n8n-Instanz und wählen Sie "Aus JSON importieren". Fügen Sie die Konfiguration ein und passen Sie die Anmeldedaten nach Bedarf an.
Für welche Szenarien ist dieser Workflow geeignet?
Experte - Marktforschung, Multimodales KI
Ist es kostenpflichtig?
Dieser Workflow ist völlig kostenlos. Beachten Sie jedoch, dass Drittanbieterdienste (wie OpenAI API), die im Workflow verwendet werden, möglicherweise kostenpflichtig sind.
Verwandte Workflows
Automatisch auf WooCommerce veröffentlichen_Vorlage
Automatisches Umwandeln von Telegram-Kanal-Beiträgen in WooCommerce-Produkte
If
Set
Code
+
If
Set
Code
26 NodesShohani
Content-Erstellung
AI Image Generation & Editing with Google Gemini and Telegram Bot
KI-Bildgenerierung und -bearbeitung basierend auf Google Gemini sowie Telegram-Bot
If
Set
Code
+
If
Set
Code
28 NodesSanthej Kallada
Content-Erstellung
AI-Powered Multi-Platform Social Media Content Factory with Dynamic System Prompts & GPT-4o
If
Set
Code
+
If
Set
Code
100 NodesAmit Mehta
Content-Erstellung
Automatischer Motor für virale Inhalte auf LinkedIn und X
Automatisiertes Erstellen und Veröffentlichen von viralen Inhalten für LinkedIn und X mittels KI
If
Set
Wait
+
If
Set
Wait
156 NodesDiptamoy Barman
Content-Erstellung
1. Playlist-Details-Einstellungen für Roboter-Kopie
Erstelle KI-generierte YouTube-Musik-Playlists mit Suno, GPT-4, Runway und Creatomate
If
Set
Code
+
If
Set
Code
203 NodesJoseph
Content-Erstellung
Authentische KI-generierte UGV-Werbevideos mit GPT-4o, ElevenLabs und WaveSpeed Lip-Sync erstellen
Erstelle realistische UGC-Werbefilme mit GPT-4o, ElevenLabs und WaveSpeed Lip Sync
If
Set
Wait
+
If
Set
Wait
38 NodesMuhammad Farooq Iqbal
Content-Erstellung
Workflow-Informationen
Schwierigkeitsgrad
Experte
Anzahl der Nodes24
Kategorie2
Node-Typen9
Autor
Externe Links
Auf n8n.io ansehen →
Diesen Workflow teilen