AutomationFlowsSlack & Telegram › Aipa - Multi-business Calendar Management

Aipa - Multi-business Calendar Management

AIPA - Multi-Business Calendar Management. Uses telegram, supabase, telegramTrigger, googleCalendar. Webhook trigger; 20 nodes.

Webhook trigger★★★★☆ complexity20 nodesTelegramSupabaseTelegram TriggerGoogle Calendar
Slack & Telegram Trigger: Webhook Nodes: 20 Complexity: ★★★★☆ Added:

This workflow follows the Supabase → Telegram recipe pattern — see all workflows that pair these two integrations.

The workflow JSON

Copy or download the full n8n JSON below. Paste it into a new n8n workflow, add your credentials, activate. Full import guide →

Download .json
{
  "name": "AIPA - Multi-Business Calendar Management",
  "nodes": [
    {
      "parameters": {
        "conditions": {
          "string": [
            {
              "value1": "={{ $json.message.text }}",
              "operation": "startsWith",
              "value2": "/calendar"
            }
          ]
        }
      },
      "id": "webhook-trigger",
      "name": "Calendar Command Trigger",
      "type": "n8n-nodes-base.webhook",
      "typeVersion": 1,
      "position": [
        250,
        300
      ]
    },
    {
      "parameters": {
        "chatId": "={{ $json.message.chat.id }}",
        "text": "\ud83d\udcc5 **Multi-Business Calendar**\\n\\nWhat would you like to do?\\n\\n1\ufe0f\u20e3 Today's schedule\\n2\ufe0f\u20e3 This week's events\\n3\ufe0f\u20e3 Add new event\\n4\ufe0f\u20e3 Check conflicts\\n5\ufe0f\u20e3 View by business\\n6\ufe0f\u20e3 Upcoming deadlines\\n\\nReply with a number.",
        "additionalFields": {
          "parse_mode": "Markdown",
          "reply_markup": {
            "keyboard": [
              [
                "1 - Today",
                "2 - This Week"
              ],
              [
                "3 - Add Event",
                "4 - Conflicts"
              ],
              [
                "5 - By Business",
                "6 - Deadlines"
              ]
            ],
            "one_time_keyboard": true,
            "resize_keyboard": true
          }
        }
      },
      "id": "show-calendar-menu",
      "name": "Show Calendar Menu",
      "type": "n8n-nodes-base.telegram",
      "typeVersion": 1,
      "position": [
        450,
        300
      ],
      "credentials": {
        "telegramApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "operation": "executeQuery",
        "query": "SELECT * FROM calendar_events WHERE DATE(event_date) = CURRENT_DATE ORDER BY event_time ASC",
        "additionalFields": {}
      },
      "id": "get-today-events",
      "name": "Get Today's Events",
      "type": "n8n-nodes-base.supabase",
      "typeVersion": 1,
      "position": [
        650,
        200
      ],
      "credentials": {
        "supabaseApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "functionCode": "// Format today's schedule\nconst events = items;\n\nif (events.length === 0) {\n  return [{\n    json: {\n      message: \"\ud83d\udced No events scheduled for today\"\n    }\n  }];\n}\n\nlet message = \"\ud83d\udcc5 **Today's Schedule**\\n\";\nmessage += new Date().toLocaleDateString('en-GB', { weekday: 'long', day: 'numeric', month: 'long' });\nmessage += \"\\n\\n\";\n\nfor (const event of events) {\n  const time = event.json.event_time ? event.json.event_time.substring(0, 5) : 'All day';\n  const business = event.json.business_context || 'Personal';\n  const businessEmoji = {\n    'woodys_creations': '\ud83c\udf81',\n    'dj_business': '\ud83c\udfb5',\n    'bmf_work': '\ud83d\udcbc',\n    'pub': '\ud83c\udf7a',\n    'personal': '\ud83d\udc64'\n  }[business] || '\ud83d\udccc';\n  \n  message += `${businessEmoji} **${time}** - ${business.replace('_', ' ').toUpperCase()}\\n`;\n  message += `   ${event.json.title}\\n`;\n  if (event.json.location) {\n    message += `   \ud83d\udccd ${event.json.location}\\n`;\n  }\n  if (event.json.notes) {\n    message += `   \ud83d\udcdd ${event.json.notes}\\n`;\n  }\n  message += `\\n`;\n}\n\nreturn [{\n  json: {\n    message: message,\n    event_count: events.length\n  }\n}];"
      },
      "id": "format-today-schedule",
      "name": "Format Today's Schedule",
      "type": "n8n-nodes-base.function",
      "typeVersion": 1,
      "position": [
        850,
        200
      ]
    },
    {
      "parameters": {
        "chatId": "={{ $node[\"Calendar Command Trigger\"].json.message.chat.id }}",
        "text": "={{ $json.message }}",
        "additionalFields": {
          "parse_mode": "Markdown"
        }
      },
      "id": "send-today-schedule",
      "name": "Send Today's Schedule",
      "type": "n8n-nodes-base.telegram",
      "typeVersion": 1,
      "position": [
        1050,
        200
      ],
      "credentials": {
        "telegramApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "operation": "executeQuery",
        "query": "SELECT * FROM calendar_events WHERE event_date BETWEEN CURRENT_DATE AND DATE_ADD(CURRENT_DATE, INTERVAL 7 DAY) ORDER BY event_date, event_time ASC",
        "additionalFields": {}
      },
      "id": "get-week-events",
      "name": "Get This Week's Events",
      "type": "n8n-nodes-base.supabase",
      "typeVersion": 1,
      "position": [
        650,
        300
      ],
      "credentials": {
        "supabaseApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "functionCode": "// Format week's events\nconst events = items;\n\nif (events.length === 0) {\n  return [{\n    json: {\n      message: \"\ud83d\udced No events scheduled this week\"\n    }\n  }];\n}\n\nlet message = \"\ud83d\udcc5 **This Week's Events**\\n\\n\";\n\n// Group by date\nconst eventsByDate = {};\n\nfor (const event of events) {\n  const date = event.json.event_date;\n  if (!eventsByDate[date]) {\n    eventsByDate[date] = [];\n  }\n  eventsByDate[date].push(event.json);\n}\n\n// Sort and format\nconst dates = Object.keys(eventsByDate).sort();\n\nfor (const date of dates) {\n  const dateObj = new Date(date);\n  const dateStr = dateObj.toLocaleDateString('en-GB', { weekday: 'short', day: 'numeric', month: 'short' });\n  const isToday = date === new Date().toISOString().split('T')[0];\n  \n  message += isToday ? `**${dateStr} (TODAY)**\\n` : `**${dateStr}**\\n`;\n  \n  for (const event of eventsByDate[date]) {\n    const time = event.event_time ? event.event_time.substring(0, 5) : 'All day';\n    const business = event.business_context || 'Personal';\n    const businessEmoji = {\n      'woodys_creations': '\ud83c\udf81',\n      'dj_business': '\ud83c\udfb5',\n      'bmf_work': '\ud83d\udcbc',\n      'pub': '\ud83c\udf7a',\n      'personal': '\ud83d\udc64'\n    }[business] || '\ud83d\udccc';\n    \n    message += `  ${time} ${businessEmoji} ${event.title}\\n`;\n  }\n  message += `\\n`;\n}\n\nmessage += `**Total: ${events.length} events**`;\n\nreturn [{\n  json: {\n    message: message,\n    event_count: events.length\n  }\n}];"
      },
      "id": "format-week-events",
      "name": "Format Week's Events",
      "type": "n8n-nodes-base.function",
      "typeVersion": 1,
      "position": [
        850,
        300
      ]
    },
    {
      "parameters": {
        "chatId": "={{ $node[\"Calendar Command Trigger\"].json.message.chat.id }}",
        "text": "={{ $json.message }}",
        "additionalFields": {
          "parse_mode": "Markdown"
        }
      },
      "id": "send-week-events",
      "name": "Send Week's Events",
      "type": "n8n-nodes-base.telegram",
      "typeVersion": 1,
      "position": [
        1050,
        300
      ],
      "credentials": {
        "telegramApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "chatId": "={{ $node[\"Calendar Command Trigger\"].json.message.chat.id }}",
        "text": "\ud83d\udcdd **Add New Calendar Event**\\n\\nPlease provide:\\n\\n1. Title\\n2. Date (YYYY-MM-DD)\\n3. Time (HH:MM) or 'all-day'\\n4. Business (woodys/dj/bmf/pub/personal)\\n5. Location (optional)\\n6. Notes (optional)\\n\\nExample:\\nClient meeting\\n2025-12-15\\n14:00\\nwoodys\\nTheir office\\nDiscuss new product line",
        "additionalFields": {}
      },
      "id": "ask-event-details",
      "name": "Ask for Event Details",
      "type": "n8n-nodes-base.telegram",
      "typeVersion": 1,
      "position": [
        650,
        400
      ],
      "credentials": {
        "telegramApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "updates": [
          "message"
        ]
      },
      "id": "wait-for-event-details",
      "name": "Wait for Event Details",
      "type": "n8n-nodes-base.telegramTrigger",
      "typeVersion": 1,
      "position": [
        850,
        400
      ]
    },
    {
      "parameters": {
        "functionCode": "// Parse event details\nconst input = items[0].json.message.text;\nconst lines = input.split('\\n').map(l => l.trim()).filter(l => l);\n\nif (lines.length < 4) {\n  return [{\n    json: {\n      error: true,\n      message: \"\u274c Missing required information (need at least title, date, time, business)\"\n    }\n  }];\n}\n\nconst title = lines[0];\nconst eventDate = lines[1];\nconst eventTime = lines[2].toLowerCase() === 'all-day' ? null : lines[2];\nconst business = lines[3].toLowerCase().replace(/\\s+/g, '_');\nconst location = lines[4] || null;\nconst notes = lines[5] || null;\n\nreturn [{\n  json: {\n    error: false,\n    title: title,\n    event_date: eventDate,\n    event_time: eventTime,\n    business_context: business,\n    location: location,\n    notes: notes,\n    created_at: new Date().toISOString()\n  }\n}];"
      },
      "id": "parse-event-details",
      "name": "Parse Event Details",
      "type": "n8n-nodes-base.function",
      "typeVersion": 1,
      "position": [
        1050,
        400
      ]
    },
    {
      "parameters": {
        "operation": "executeQuery",
        "query": "=SELECT * FROM calendar_events WHERE event_date = '{{ $json.event_date }}' AND event_time IS NOT NULL AND ABS(TIMESTAMPDIFF(MINUTE, event_time, '{{ $json.event_time }}')) < 60",
        "additionalFields": {}
      },
      "id": "check-conflicts",
      "name": "Check for Conflicts",
      "type": "n8n-nodes-base.supabase",
      "typeVersion": 1,
      "position": [
        1250,
        400
      ],
      "credentials": {
        "supabaseApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "conditions": {
          "number": [
            {
              "value1": "={{ $json.length }}",
              "operation": "equal",
              "value2": 0
            }
          ]
        }
      },
      "id": "check-if-clear",
      "name": "Check if Time Clear",
      "type": "n8n-nodes-base.if",
      "typeVersion": 1,
      "position": [
        1450,
        400
      ]
    },
    {
      "parameters": {
        "operation": "insert",
        "table": "calendar_events",
        "columns": "title, event_date, event_time, business_context, location, notes, created_at",
        "additionalFields": {}
      },
      "id": "save-event",
      "name": "Save Event to Calendar",
      "type": "n8n-nodes-base.supabase",
      "typeVersion": 1,
      "position": [
        1650,
        350
      ],
      "credentials": {
        "supabaseApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "resource": "event",
        "operation": "create",
        "calendar": "primary",
        "start": "={{ $node[\"Parse Event Details\"].json.event_date }}T{{ $node[\"Parse Event Details\"].json.event_time || '00:00' }}:00",
        "end": "={{ $node[\"Parse Event Details\"].json.event_date }}T{{ $node[\"Parse Event Details\"].json.event_time || '23:59' }}:00",
        "summary": "={{ $node[\"Parse Event Details\"].json.title }}",
        "options": {
          "description": "={{ $node[\"Parse Event Details\"].json.notes }}",
          "location": "={{ $node[\"Parse Event Details\"].json.location }}"
        }
      },
      "id": "add-to-google-calendar",
      "name": "Add to Google Calendar",
      "type": "n8n-nodes-base.googleCalendar",
      "typeVersion": 1,
      "position": [
        1850,
        350
      ],
      "credentials": {
        "googleCalendarOAuth2": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "chatId": "={{ $node[\"Wait for Event Details\"].json.message.chat.id }}",
        "text": "=\u2705 **Event Added Successfully!**\\n\\n\ud83d\udcc5 {{ $node[\"Parse Event Details\"].json.event_date }}\\n\u23f0 {{ $node[\"Parse Event Details\"].json.event_time || 'All day' }}\\n\ud83d\udccc {{ $node[\"Parse Event Details\"].json.title }}\\n\ud83c\udfe2 {{ $node[\"Parse Event Details\"].json.business_context }}\\n\\n\u2713 Saved to database\\n\u2713 Added to Google Calendar",
        "additionalFields": {
          "parse_mode": "Markdown"
        }
      },
      "id": "confirm-event-added",
      "name": "Confirm Event Added",
      "type": "n8n-nodes-base.telegram",
      "typeVersion": 1,
      "position": [
        2050,
        350
      ],
      "credentials": {
        "telegramApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "chatId": "={{ $node[\"Wait for Event Details\"].json.message.chat.id }}",
        "text": "=\u26a0\ufe0f **Time Conflict Detected!**\\n\\nThere's already an event scheduled around this time:\\n\\n{{ $node[\"Check for Conflicts\"].json[0].title }}\\n\u23f0 {{ $node[\"Check for Conflicts\"].json[0].event_time }}\\n\\nWould you like to:\\n1. Add anyway\\n2. Choose different time\\n3. Cancel",
        "additionalFields": {
          "parse_mode": "Markdown"
        }
      },
      "id": "warn-conflict",
      "name": "Warn About Conflict",
      "type": "n8n-nodes-base.telegram",
      "typeVersion": 1,
      "position": [
        1650,
        450
      ],
      "credentials": {
        "telegramApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "operation": "executeQuery",
        "query": "SELECT * FROM calendar_events WHERE event_date >= CURRENT_DATE AND business_context IN ('dj_business', 'woodys_creations', 'bmf_work') ORDER BY event_date ASC LIMIT 20",
        "additionalFields": {}
      },
      "id": "get-upcoming-deadlines",
      "name": "Get Upcoming Deadlines",
      "type": "n8n-nodes-base.supabase",
      "typeVersion": 1,
      "position": [
        650,
        500
      ],
      "credentials": {
        "supabaseApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "functionCode": "// Format upcoming deadlines\nconst events = items;\n\nif (events.length === 0) {\n  return [{\n    json: {\n      message: \"\ud83d\udced No upcoming deadlines\"\n    }\n  }];\n}\n\nlet message = \"\u23f0 **Upcoming Deadlines**\\n\\n\";\n\nfor (const event of events) {\n  const date = new Date(event.json.event_date);\n  const today = new Date();\n  today.setHours(0, 0, 0, 0);\n  const daysUntil = Math.ceil((date - today) / (1000 * 60 * 60 * 24));\n  \n  const dateStr = date.toLocaleDateString('en-GB', { day: 'numeric', month: 'short' });\n  const business = event.json.business_context || 'Unknown';\n  const businessEmoji = {\n    'woodys_creations': '\ud83c\udf81',\n    'dj_business': '\ud83c\udfb5',\n    'bmf_work': '\ud83d\udcbc',\n    'pub': '\ud83c\udf7a'\n  }[business] || '\ud83d\udccc';\n  \n  // Urgency indicator\n  const urgency = daysUntil <= 1 ? '\ud83d\udd34' : daysUntil <= 3 ? '\ud83d\udfe1' : '\ud83d\udfe2';\n  \n  message += `${urgency} ${businessEmoji} **${event.json.title}**\\n`;\n  message += `   \ud83d\udcc5 ${dateStr} (${daysUntil} days)\\n`;\n  if (event.json.notes) {\n    message += `   \ud83d\udcdd ${event.json.notes}\\n`;\n  }\n  message += `\\n`;\n}\n\nreturn [{\n  json: {\n    message: message,\n    deadline_count: events.length\n  }\n}];"
      },
      "id": "format-deadlines",
      "name": "Format Deadlines",
      "type": "n8n-nodes-base.function",
      "typeVersion": 1,
      "position": [
        850,
        500
      ]
    },
    {
      "parameters": {
        "chatId": "={{ $node[\"Calendar Command Trigger\"].json.message.chat.id }}",
        "text": "={{ $json.message }}",
        "additionalFields": {
          "parse_mode": "Markdown"
        }
      },
      "id": "send-deadlines",
      "name": "Send Deadlines",
      "type": "n8n-nodes-base.telegram",
      "typeVersion": 1,
      "position": [
        1050,
        500
      ],
      "credentials": {
        "telegramApi": {
          "name": "<your credential>"
        }
      }
    }
  ],
  "connections": {
    "Calendar Command Trigger": {
      "main": [
        [
          {
            "node": "Show Calendar Menu",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Show Calendar Menu": {
      "main": [
        [
          {
            "node": "Get Today's Events",
            "type": "main",
            "index": 0
          },
          {
            "node": "Get This Week's Events",
            "type": "main",
            "index": 0
          },
          {
            "node": "Ask for Event Details",
            "type": "main",
            "index": 0
          },
          {
            "node": "Get Upcoming Deadlines",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get Today's Events": {
      "main": [
        [
          {
            "node": "Format Today's Schedule",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Format Today's Schedule": {
      "main": [
        [
          {
            "node": "Send Today's Schedule",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get This Week's Events": {
      "main": [
        [
          {
            "node": "Format Week's Events",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Format Week's Events": {
      "main": [
        [
          {
            "node": "Send Week's Events",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Ask for Event Details": {
      "main": [
        [
          {
            "node": "Wait for Event Details",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Wait for Event Details": {
      "main": [
        [
          {
            "node": "Parse Event Details",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Parse Event Details": {
      "main": [
        [
          {
            "node": "Check for Conflicts",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Check for Conflicts": {
      "main": [
        [
          {
            "node": "Check if Time Clear",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Check if Time Clear": {
      "main": [
        [
          {
            "node": "Save Event to Calendar",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Warn About Conflict",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Save Event to Calendar": {
      "main": [
        [
          {
            "node": "Add to Google Calendar",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Add to Google Calendar": {
      "main": [
        [
          {
            "node": "Confirm Event Added",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get Upcoming Deadlines": {
      "main": [
        [
          {
            "node": "Format Deadlines",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Format Deadlines": {
      "main": [
        [
          {
            "node": "Send Deadlines",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  },
  "settings": {
    "executionOrder": "v1"
  },
  "staticData": null,
  "tags": [],
  "triggerCount": 0,
  "updatedAt": "2025-11-01T18:00:00.000Z",
  "versionId": "1"
}

Credentials you'll need

Each integration node will prompt for credentials when you import. We strip credential IDs before publishing — you'll add your own.

Pro

For the full experience including quality scoring and batch install features for each workflow upgrade to Pro

About this workflow

AIPA - Multi-Business Calendar Management. Uses telegram, supabase, telegramTrigger, googleCalendar. Webhook trigger; 20 nodes.

Source: https://github.com/DirtyDerv/AIPA/blob/defb52161b0d387cd66b2a6d3bbb1e71b4afc6ae/n8n-workflows/06-calendar-management.json — original creator credit. Request a take-down →

More Slack & Telegram workflows → · Browse all categories →

Related workflows

Workflows that share integrations, category, or trigger type with this one. All free to copy and import.

Slack & Telegram

AIPA - BMF Work Logging. Uses telegram, telegramTrigger, supabase, httpRequest. Webhook trigger; 19 nodes.

Telegram, Telegram Trigger, Supabase +1
Slack & Telegram

clients kept booking meetings during my prayer times. i'd either miss a prayer or scramble to reschedule. the problem wasn't the clients — it was that my calendar had no blocked windows for salah. i n

Telegram Trigger, HTTP Request, Google Calendar +3
Slack & Telegram

This workflow tracks upcoming subscription expiry dates stored in Supabase and automatically sends personalized renewal-reminder messages to each customer via Telegram. It is designed to be triggered

Supabase, Telegram
Slack & Telegram

Zalo User Demo Connect Telegram. Uses n8n, n8n-nodes-zalo-user, telegram, telegramTrigger. Webhook trigger; 19 nodes.

n8n, N8N Nodes Zalo User, Telegram +1
Slack & Telegram

Telegram-auth. Uses telegramTrigger, telegram, supabase, httpRequest. Event-driven trigger; 18 nodes.

Telegram Trigger, Telegram, Supabase +1