8
n8n 한국어amn8n.com

여행 일정 날씨 자동 예보

고급

이것은Personal Productivity분야의자동화 워크플로우로, 17개의 노드를 포함합니다.주로 If, Code, Wait, Telegram, HttpRequest 등의 노드를 사용하며. 에서Google Calendar자동推送行程天气预报로Telegram

사전 요구사항
  • Telegram Bot Token
  • 대상 API의 인증 정보가 필요할 수 있음

카테고리

워크플로우 미리보기
노드 연결 관계를 시각적으로 표시하며, 확대/축소 및 이동을 지원합니다
워크플로우 내보내기
다음 JSON 구성을 복사하여 n8n에 가져오면 이 워크플로우를 사용할 수 있습니다
{
  "meta": {
    "instanceId": "e0abec5d9b13345e424c0dbbc512271f89fb17de3b268697e13a797de2271404"
  },
  "nodes": [
    {
      "id": "7df92b27-05c7-4c4a-9b2f-76883f0d8974",
      "name": "If1",
      "type": "n8n-nodes-base.if",
      "position": [
        624,
        -64
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "8e217cc9-d842-4b92-a62b-b79e99a059df",
              "operator": {
                "type": "number",
                "operation": "gt"
              },
              "leftValue": "={{ $json.sequence }}",
              "rightValue": 0
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "40fe3671-d5ed-49fd-a342-f89df42f5657",
      "name": "여정 식별",
      "type": "n8n-nodes-base.code",
      "position": [
        400,
        -64
      ],
      "parameters": {
        "jsCode": "const travelKeywords = ['trip', 'travel', 'vacation', 'flight', 'holiday'];\n\nreturn items.filter(item => {\n  const title = (item.json.summary || '').toLowerCase();\n  const description = (item.json.description || '').toLowerCase();\n\n  return travelKeywords.some(keyword => title.includes(keyword) || description.includes(keyword));\n});\n"
      },
      "typeVersion": 2
    },
    {
      "id": "41df49be-15c4-4c83-8c69-6c8cc109ac34",
      "name": "위치 추출",
      "type": "n8n-nodes-base.code",
      "position": [
        848,
        -64
      ],
      "parameters": {
        "jsCode": "return items.map(item => {\n  const startDate = item.json.start.dateTime || item.json.start.date;\n  const endDate = item.json.end.dateTime || item.json.end.date;\n\n  // Initialize location variable\n  let location = null;\n\n  // Extract destination from summary first (e.g. \"Flight to Istanbul\")\n  const summary = (item.json.summary || '').toLowerCase();\n  const matchSummary = summary.match(/to ([a-zA-Z\\s,]+)/);\n  if (matchSummary && matchSummary[1]) {\n    location = matchSummary[1].trim();\n  }\n\n  // If no destination yet, try description (e.g. \"Flight from Mauritius (port Louis) to Istanbul\")\n  if (!location) {\n    const description = (item.json.description || '').toLowerCase();\n    // Match pattern after \"to \"\n    const matchDescription = description.match(/to ([a-zA-Z\\s,]+)/);\n    if (matchDescription && matchDescription[1]) {\n      location = matchDescription[1].trim();\n    }\n  }\n\n  // Only use the location field if above patterns fail or if location is not a \"from\" location\n  if (!location && item.json.location) {\n    const locLower = item.json.location.toLowerCase();\n    if (!locLower.startsWith('from ')) {  // Avoid departure locations starting with \"from\"\n      location = item.json.location;\n    }\n  }\n\n  // Final fallback if no location found\n  if (!location) {\n    location = null; // or 'YOUR_DEFAULT_TRIP_LOCATION'\n  }\n\n  return {\n    json: {\n      startDate,\n      endDate,\n      location\n    }\n  };\n});\n"
      },
      "typeVersion": 2
    },
    {
      "id": "1c3d2277-df1f-4178-bdba-bff40a182c2d",
      "name": "대기",
      "type": "n8n-nodes-base.wait",
      "position": [
        1104,
        320
      ],
      "webhookId": "f1f55baf-71bd-4fc9-b81d-b3f0b8092d03",
      "parameters": {
        "resume": "specificTime",
        "dateTime": "={{ new Date(new Date($('Extract locations').item.json.startDate).getTime() - 24 * 60 * 60 * 1000).toISOString() }}"
      },
      "typeVersion": 1.1
    },
    {
      "id": "0d3f1ec2-2377-46e3-84bc-c303adddb825",
      "name": "Sticky Note4",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -448,
        -400
      ],
      "parameters": {
        "width": 560,
        "height": 752,
        "content": "## How it works\nWhen a calendar event is created or updated, identified as trip, provides timely weather alerts and forecasts tailored to travel dates and locations.\n\n## Step-by-step\n\n📅 **Google Calendar Triggers** (Event Created/Updated): \nThe workflow starts immediately upon creation or update of any calendar event, enabling real-time detection of new or changed travel plans.\n\n✈ **Identify Trips & Extract Locations**: \nFilters these calendar events to detect travel-related trips by matching keywords such as \"trip,\" \"flight,\" or \"vacation\" in titles or descriptions and extract start and end dates & the trip destination.\n\n🌐 **Get Forecast & send it**: \nUsing Visual Crossing API (1000 free daily requests) fetches the detailed weather forecast and alert data for the trip location then formats the raw weather data into a readable summary 🌤️🌪🌀, and eventual severe weather alerts.\n\n📲 📧 **Send Forecast**: \nSends the forecast summary with alerts via Telegram to keep the user informed instantly.\n\n⌛**One day before the trip**: \nPauses the workflow until exactly one day before the trip start date, ensuring a timely second fetch when more accurate or updated weather data is available and the updated forecast is sent.\n\n## Optional\nYou can replace the Telegram node with email, WhatsApp, Slack, SMS notifications, or add multiple notification nodes to receive them across all desired channels."
      },
      "typeVersion": 1
    },
    {
      "id": "79b81985-724d-4208-a225-25ecde0851e7",
      "name": "이벤트 생성됨",
      "type": "n8n-nodes-base.googleCalendarTrigger",
      "position": [
        176,
        -160
      ],
      "parameters": {
        "options": {},
        "pollTimes": {
          "item": [
            {
              "mode": "everyMinute"
            }
          ]
        },
        "triggerOn": "eventCreated",
        "calendarId": {
          "__rl": true,
          "mode": "list",
          "value": "bara.razvan@gmail.com",
          "cachedResultName": "bara.razvan@gmail.com"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "38413099-7d19-4c06-bec7-a2d542607474",
      "name": "이벤트 업데이트됨",
      "type": "n8n-nodes-base.googleCalendarTrigger",
      "position": [
        176,
        32
      ],
      "parameters": {
        "options": {},
        "pollTimes": {
          "item": [
            {
              "mode": "everyMinute"
            }
          ]
        },
        "triggerOn": "eventUpdated",
        "calendarId": {
          "__rl": true,
          "mode": "list",
          "value": "bara.razvan@gmail.com",
          "cachedResultName": "bara.razvan@gmail.com"
        }
      },
      "credentials": {},
      "typeVersion": 1
    },
    {
      "id": "1cac0052-349b-4ae2-8c4e-b1a63bd834f4",
      "name": "예보 전송",
      "type": "n8n-nodes-base.telegram",
      "position": [
        1808,
        -64
      ],
      "webhookId": "7eb54f22-cbed-498d-b1b7-ccabe38b4a06",
      "parameters": {
        "operation": "send"
      },
      "notesInFlow": [
        {
          "note": "Sends the trip weather forecast summary to user via Telegram."
        }
      ],
      "typeVersion": 1
    },
    {
      "id": "bb15bccd-f857-4de6-907f-7a48457a125f",
      "name": "조회 URL 구성",
      "type": "n8n-nodes-base.code",
      "position": [
        1072,
        -64
      ],
      "parameters": {
        "jsCode": "const location = encodeURIComponent($json.location);\nconst startDate = $json.startDate.split('T')[0]; // date only\nconst endDate = $json.endDate.split('T')[0]; // date only\nconst apiKey = '[your API]';\n\nconst url = `https://weather.visualcrossing.com/VisualCrossingWebServices/rest/services/timeline/${location}/${startDate}/${endDate}?unitGroup=metric&key=${apiKey}&include=days,alerts`;\n\nreturn [{ json: { url } }];\n"
      },
      "typeVersion": 2
    },
    {
      "id": "e29e2ff1-46fd-44c5-ab8f-02d345586e41",
      "name": "업데이트된 목적지 날씨 예보 가져오기",
      "type": "n8n-nodes-base.httpRequest",
      "notes": "One day before the trip",
      "position": [
        1328,
        320
      ],
      "parameters": {
        "url": "={{ $json.url }}",
        "options": {}
      },
      "notesInFlow": [
        {
          "note": "Fetches weather forecast and alerts for trip location and dates from Visual Crossing."
        }
      ],
      "typeVersion": 1
    },
    {
      "id": "c69a55de-bbf3-4921-bd89-24d4b8826111",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        368,
        -160
      ],
      "parameters": {
        "color": 7,
        "width": 608,
        "height": 240,
        "content": "## Identify \n**if** the event is a trip\n**Then** > extracting destination and period"
      },
      "typeVersion": 1
    },
    {
      "id": "50def3d9-67bc-4f5c-b2a4-18f4235fffec",
      "name": "Sticky Note8",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1024,
        208
      ],
      "parameters": {
        "color": 6,
        "width": 448,
        "height": 288,
        "content": "## Update the forecast one day before the trip\nWait one day before the trip and request again the forecast"
      },
      "typeVersion": 1
    },
    {
      "id": "8aec9d53-2af5-4e3f-87a2-f0f67a2497e3",
      "name": "Sticky Note6",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1008,
        -160
      ],
      "parameters": {
        "color": 7,
        "width": 480,
        "height": 672,
        "content": "## Get Forecast\n"
      },
      "typeVersion": 1
    },
    {
      "id": "57b375da-2354-4b04-a6ee-b510bed576d0",
      "name": "Sticky Note3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1536,
        -160
      ],
      "parameters": {
        "color": 7,
        "width": 416,
        "height": 256,
        "content": "## Send notification\nMake sure Telegram credentials and chat ID are set in the node."
      },
      "typeVersion": 1
    },
    {
      "id": "b4b8e95d-3ea8-4ea2-ab88-a889a74d6818",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        128,
        -272
      ],
      "parameters": {
        "color": 7,
        "width": 192,
        "height": 464,
        "content": "## Trigger:\n**EVENT**\nCreated or updated"
      },
      "typeVersion": 1
    },
    {
      "id": "5c65c141-7527-43b9-8e85-bd8f1291b54e",
      "name": "목적지 날씨 예보 가져오기",
      "type": "n8n-nodes-base.httpRequest",
      "notes": "At the event creation/update",
      "position": [
        1296,
        -64
      ],
      "parameters": {
        "url": "={{ $json.url }}",
        "options": {}
      },
      "notesInFlow": [
        {
          "note": "Fetches weather forecast and alerts for trip location and dates from Visual Crossing."
        }
      ],
      "typeVersion": 1
    },
    {
      "id": "b92af965-eecf-4019-b5cf-ca38e8ee9928",
      "name": "메시지 포맷팅",
      "type": "n8n-nodes-base.code",
      "position": [
        1584,
        -64
      ],
      "parameters": {
        "jsCode": "return items.map(item => {\n  let forecastSummary = `Weather forecast for your trip to ${item.json.address || 'destination'} from ${item.json.days[0].datetime} to ${item.json.days[item.json.days.length - 1].datetime}:\\n`;\n\n  item.json.days.forEach(day => {\n    const precipprob = day.precipprob !== undefined ? `, Precip Prob: ${day.precipprob}%` : '';\n    const preciptype = day.preciptype ? `, Precip Type: ${day.preciptype.join(\", \")}` : '';\n    const conditions = day.conditions ? `, Conditions: ${day.conditions}` : '';\n    const description = day.description ? `,  ${day.description}` : '';\n    forecastSummary += `${day.datetime}: Max ${day.tempmax}°C, Min ${day.tempmin}°C${precipprob}${preciptype}${conditions}${description}\\n`;\n  });\n\n  if (item.json.alerts && item.json.alerts.length > 0) {\n    forecastSummary += `\\nALERTS:\\n`;\n    item.json.alerts.forEach(alert => {\n      forecastSummary += `${alert.description}\\n`;\n    });\n  }\n\n  return {\n    json: { forecastSummary }\n  };\n});\n"
      },
      "typeVersion": 2
    }
  ],
  "pinData": {},
  "connections": {
    "7df92b27-05c7-4c4a-9b2f-76883f0d8974": {
      "main": [
        [
          {
            "node": "41df49be-15c4-4c83-8c69-6c8cc109ac34",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "1c3d2277-df1f-4178-bdba-bff40a182c2d": {
      "main": [
        [
          {
            "node": "e29e2ff1-46fd-44c5-ab8f-02d345586e41",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "79b81985-724d-4208-a225-25ecde0851e7": {
      "main": [
        [
          {
            "node": "40fe3671-d5ed-49fd-a342-f89df42f5657",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "38413099-7d19-4c06-bec7-a2d542607474": {
      "main": [
        [
          {
            "node": "40fe3671-d5ed-49fd-a342-f89df42f5657",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "b92af965-eecf-4019-b5cf-ca38e8ee9928": {
      "main": [
        [
          {
            "node": "1cac0052-349b-4ae2-8c4e-b1a63bd834f4",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "40fe3671-d5ed-49fd-a342-f89df42f5657": {
      "main": [
        [
          {
            "node": "7df92b27-05c7-4c4a-9b2f-76883f0d8974",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "41df49be-15c4-4c83-8c69-6c8cc109ac34": {
      "main": [
        [
          {
            "node": "bb15bccd-f857-4de6-907f-7a48457a125f",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "bb15bccd-f857-4de6-907f-7a48457a125f": {
      "main": [
        [
          {
            "node": "1c3d2277-df1f-4178-bdba-bff40a182c2d",
            "type": "main",
            "index": 0
          },
          {
            "node": "5c65c141-7527-43b9-8e85-bd8f1291b54e",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "5c65c141-7527-43b9-8e85-bd8f1291b54e": {
      "main": [
        [
          {
            "node": "b92af965-eecf-4019-b5cf-ca38e8ee9928",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "e29e2ff1-46fd-44c5-ab8f-02d345586e41": {
      "main": [
        [
          {
            "node": "b92af965-eecf-4019-b5cf-ca38e8ee9928",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}
자주 묻는 질문

이 워크플로우를 어떻게 사용하나요?

위의 JSON 구성 코드를 복사하여 n8n 인스턴스에서 새 워크플로우를 생성하고 "JSON에서 가져오기"를 선택한 후, 구성을 붙여넣고 필요에 따라 인증 설정을 수정하세요.

이 워크플로우는 어떤 시나리오에 적합한가요?

고급 - 개인 생산성

유료인가요?

이 워크플로우는 완전히 무료이며 직접 가져와 사용할 수 있습니다. 다만, 워크플로우에서 사용하는 타사 서비스(예: OpenAI API)는 사용자 직접 비용을 지불해야 할 수 있습니다.

워크플로우 정보
난이도
고급
노드 수17
카테고리1
노드 유형7
난이도 설명

고급 사용자를 위한 16+개 노드의 복잡한 워크플로우

저자
Razvan Bara

Razvan Bara

@amzneer

Whether you're launching your first product or scaling, I'll help you build an AI-powered, data-driven system that runs your business while you focus on strategic growth. Let's discuss how strategic optimization combined with business intelligence and custom AI agents can transform your operations and accelerate your success. Ready to scale smarter with AI and data? Let's talk.

외부 링크
n8n.io에서 보기

이 워크플로우 공유

카테고리

카테고리: 34