将Google Calendar的面试提醒(10分钟前)发送至Slack私信
中级
这是一个HR领域的自动化工作流,包含 10 个节点。主要使用 If, Set, Cron, Slack, Function 等节点。 将Google Calendar的面试提醒(10分钟前)发送至Slack私信
前置要求
- •Slack Bot Token 或 Webhook URL
分类
工作流预览
可视化展示节点连接关系,支持缩放和平移
导出工作流
复制以下 JSON 配置到 n8n 导入,即可使用此工作流
{
"id": "HrXWJRDS0O4PpRJ5",
"meta": {
"instanceId": "14e4c77104722ab186539dfea5182e419aecc83d85963fe13f6de862c875ebfa"
},
"name": "将Google Calendar的面试提醒(10分钟前)发送至Slack私信",
"tags": [],
"nodes": [
{
"id": "171b7858-d94e-409f-b368-7a59a11d09b8",
"name": "定时触发器",
"type": "n8n-nodes-base.cron",
"position": [
-1600,
100
],
"parameters": {},
"typeVersion": 1
},
{
"id": "a569b753-23c3-4226-906e-6bfc5992b4ef",
"name": "准备提醒",
"type": "n8n-nodes-base.function",
"position": [
-940,
100
],
"parameters": {
"functionCode": "const now = new Date();\nconst leadMinutes = parseInt($node['Set: Config'].json['LEAD_MINUTES']);\nconst companyDomain = $node['Set: Config'].json['COMPANY_DOMAIN'];\nconst fileritems = [];\n\n// Process each calendar event\nfor (const item of items) {\n const eventData = item.json;\n \n // Skip if already started\n if (!eventData.attendees || !eventData.start || !eventData.start.dateTime) {\n continue;\n }\n \n const startTime = new Date(eventData.start.dateTime);\n const timeDiff = (startTime - now) / (1000 * 60); // minutes\n \n // Only process events starting within lead time\n\n if (timeDiff > 0 && timeDiff <= leadMinutes) {\n\n // Extract links from description\n const description = eventData.description || '';\n const cvMatch = description.match(/CV:\\s*(https?:\\/\\/[^\\s\\n]+)/i);\n const notesMatch = description.match(/Notes:\\s*(https?:\\/\\/[^\\s\\n]+)/i);\n const meetingLinkMatch = description.match(/(https?:\\/\\/[^\\s\\n]*(?:meet\\.google\\.com|zoom\\.us|teams\\.microsoft\\.com)[^\\s\\n]*)/i) || \n eventData.hangoutLink ? [eventData.hangoutLink] : null;\n\n // Process each attendee\n\n for (const attendee of eventData.attendees) {\n // Skip organizer, declined attendees, and external emails\n if (attendee.organizer || \n attendee.responseStatus === 'declined' ||\n !attendee.email) {\n continue;\n }\n \n // Create item for each valid attendee\n fileritems.push({\n eventId: eventData.id,\n eventTitle: eventData.summary || 'Interview',\n startTime: eventData.start.dateTime,\n attendeeEmail: attendee.email,\n attendeeName: attendee.displayName || attendee.email.split('@')[0],\n cvLink: cvMatch ? cvMatch[1] : null,\n notesLink: notesMatch ? notesMatch[1] : null,\n meetingLink: meetingLinkMatch ? meetingLinkMatch[0] : eventData.htmlLink,\n localStartTime: new Date(eventData.start.dateTime).toLocaleString('en-IN', {\n timeZone: $node['Set: Config'].json['TIMEZONE'],\n weekday: 'short',\n month: 'short',\n day: 'numeric',\n hour: '2-digit',\n minute: '2-digit'\n }),\n uniqueKey: `${eventData.id}_${attendee.email}`\n });\n }\n }\n}\n\nreturn fileritems;"
},
"typeVersion": 1
},
{
"id": "d3e1408e-d8a4-4536-bb8e-afba9eb29048",
"name": "检查记录",
"type": "n8n-nodes-base.function",
"position": [
-720,
100
],
"parameters": {
"functionCode": "const uniqueKey = $json.uniqueKey;\nconst sentPings = this.getWorkflowStaticData('global').sentPings || {};\n\n// Check if already sent\nconst alreadySent = sentPings[uniqueKey] || false;\n\nreturn {\n json: {\n ...$json,\n alreadySent: alreadySent\n }\n};"
},
"typeVersion": 1
},
{
"id": "979bf30e-5ada-4e3b-a523-2a66d34a174c",
"name": "若未发送",
"type": "n8n-nodes-base.if",
"position": [
-500,
100
],
"parameters": {
"conditions": {
"boolean": [
{
"value1": "={{$json.alreadySent}}"
}
]
}
},
"typeVersion": 1
},
{
"id": "f3bb5c60-887b-4263-8624-82506edf1bdf",
"name": "找到用户?",
"type": "n8n-nodes-base.if",
"position": [
-280,
100
],
"parameters": {
"conditions": {
"boolean": [
{
"value1": "={{$json.ok}}",
"value2": true
}
]
}
},
"typeVersion": 1
},
{
"id": "2157b372-c81a-4563-9c38-a46bf7b16192",
"name": "发送私信",
"type": "n8n-nodes-base.slack",
"position": [
-60,
0
],
"parameters": {
"text": "🕙 *Interview starting in {{$node['Set: Config'].json['LEAD_MINUTES']}} minutes*\n\n*Candidate:* {{$json.eventTitle.replace('Interview', '').replace(' - ', '').trim() || 'TBD'}}\n*Time:* {{$json.localStartTime}}\n*Role:* {{$json.eventTitle.includes(' - ') ? $json.eventTitle.split(' - ')[1] : 'Interview'}}\n\n📅 <{{$json.meetingLink}}|Join Meeting>{{$json.cvLink ? '\n📋 <' + $json.cvLink + '|View CV>' : ''}}{{$json.notesLink ? '\n📝 <' + $json.notesLink + '|View Notes>' : ''}}",
"channel": "={{$json.user.id}}",
"attachments": [],
"otherOptions": {
"mrkdwn": true
},
"authentication": "oAuth2"
},
"typeVersion": 1
},
{
"id": "63b10066-efa9-4801-a817-4a8eab96c0b4",
"name": "发布至备用频道",
"type": "n8n-nodes-base.slack",
"position": [
-60,
200
],
"parameters": {
"text": "=🕙 *Interview Reminder - Unable to DM*\n\n*Interviewer:* <mailto:{{ $('Check Ledger').item.json.attendeeEmail }}|{{ $('Check Ledger').item.json.attendeeName }}>\n*Candidate:* {{$('Check Ledger').item.json.eventTitle.replace('Interview', '').replace(' - ', '').trim() || 'TBD'}}\n*Time:* {{ $('Check Ledger').item.json.startTime }}\n*Role:* {{$('Check Ledger').item.json.eventTitle.includes(' - ') ? $('Check Ledger').item.json.eventTitle.split(' - ')[1] : 'Interview'}}\n\n📅 <{{ $('Check Ledger').item.json.meetingLink }}|Join Meeting>\n{{$('Check Ledger').item.json.cvLink ? '📋 <' + $('Check Ledger').item.json.cvLink + '|View CV>' : ''}}\n{{$('Check Ledger').item.notesLink ? '📝 <' + $('Check Ledger').item.notesLink + '|View Notes>' : ''}}",
"channel": "={{$node['Set: Config'].json['FALLBACK_CHANNEL']}}",
"attachments": [],
"otherOptions": {
"mrkdwn": true
},
"authentication": "oAuth2"
},
"typeVersion": 1
},
{
"id": "ddfb1f3a-98f6-4426-bbfd-5afeebd50425",
"name": "记录已发送提醒",
"type": "n8n-nodes-base.function",
"position": [
160,
100
],
"parameters": {
"functionCode": "// Record that ping was sent\nconst uniqueKey = $json.uniqueKey;\nconst staticData = this.getWorkflowStaticData('global');\n\nif (!staticData.sentPings) {\n staticData.sentPings = {};\n}\n\nstaticData.sentPings[uniqueKey] = {\n sentAt: new Date().toISOString(),\n eventId: $json.eventId,\n attendeeEmail: $json.attendeeEmail\n};\n\nreturn {\n json: {\n ...$json,\n recorded: true\n }\n};"
},
"typeVersion": 1
},
{
"id": "f30eecea-8611-4653-8d75-cda59233246c",
"name": "设置:配置",
"type": "n8n-nodes-base.set",
"position": [
-1380,
100
],
"parameters": {
"values": {
"string": [
{
"name": "CALENDAR_NAME",
"value": "Interviews"
},
{
"name": "COMPANY_DOMAIN",
"value": "domain.com"
},
{
"name": "TIMEZONE",
"value": "Asia/Kolkata"
},
{
"name": "LEAD_MINUTES",
"value": "10"
},
{
"name": "FALLBACK_CHANNEL",
"value": "#recruiting-alerts"
}
]
},
"options": {}
},
"typeVersion": 1
},
{
"id": "af6a6ed8-0370-4f7a-9573-eeec96eb001b",
"name": "获取多个事件",
"type": "n8n-nodes-base.googleCalendar",
"position": [
-1160,
100
],
"parameters": {
"options": {},
"calendar": {
"__rl": true,
"mode": "list",
"value": "",
"cachedResultName": ""
},
"operation": "getAll"
},
"typeVersion": 1
}
],
"active": false,
"pinData": {},
"settings": {
"executionOrder": "v1"
},
"versionId": "97c7d32f-1785-4a9b-87fd-d3b58ddf3de5",
"connections": {
"Send DM": {
"main": [
[
{
"node": "Record Ping Sent",
"type": "main",
"index": 0
}
]
]
},
"Set: Config": {
"main": [
[
{
"node": "Get many events",
"type": "main",
"index": 0
}
]
]
},
"User Found?": {
"main": [
[
{
"node": "Send DM",
"type": "main",
"index": 0
}
],
[
{
"node": "Post to Fallback Channel",
"type": "main",
"index": 0
}
]
]
},
"Check Ledger": {
"main": [
[
{
"node": "If Not Already Sent",
"type": "main",
"index": 0
}
]
]
},
"Cron Trigger": {
"main": [
[
{
"node": "Set: Config",
"type": "main",
"index": 0
}
]
]
},
"Prepare Pings": {
"main": [
[
{
"node": "Check Ledger",
"type": "main",
"index": 0
}
]
]
},
"Get many events": {
"main": [
[
{
"node": "Prepare Pings",
"type": "main",
"index": 0
}
]
]
},
"If Not Already Sent": {
"main": [
[
{
"node": "User Found?",
"type": "main",
"index": 0
}
]
]
},
"Post to Fallback Channel": {
"main": [
[
{
"node": "Record Ping Sent",
"type": "main",
"index": 0
}
]
]
}
}
}常见问题
如何使用这个工作流?
复制上方的 JSON 配置代码,在您的 n8n 实例中创建新工作流并选择「从 JSON 导入」,粘贴配置后根据需要修改凭证设置即可。
这个工作流适合什么场景?
中级 - 人力资源
需要付费吗?
本工作流完全免费,您可以直接导入使用。但请注意,工作流中使用的第三方服务(如 OpenAI API)可能需要您自行付费。
相关工作流推荐
使用 HTTP Last-Modified 检查从 Google Sheets 获取职位发布过期和刷新提醒
通过 Google Sheets、HTTP 检查和 Gmail 实现职位发布过期提醒的自动化
If
Set
Code
+6
19 节点WeblineIndia
人力资源
从Google Sheets向Slack发送面试后反馈提醒(含邮件备用方案)
使用Google Sheets、Slack和Gmail自动化面试后反馈提醒
If
Gmail
Slack
+3
9 节点WeblineIndia
人力资源
使用Google Sheets和Gmail在每日结束时自动发送招聘拒绝邮件
在每日结束时自动发送招聘拒绝邮件(Google Sheets | Gmail)
If
Set
Code
+4
15 节点WeblineIndia
人力资源
绩效评估调度与提醒
使用Google Sheets、日历、邮件和Slack自动化绩效评估流程
If
Set
Code
+7
16 节点Oneclick AI Squad
人力资源
自动化SEO健康监控与报告
网站SEO健康分析(Google Sheets、PDF报告和Gmail告警)
If
Set
Code
+8
16 节点WeblineIndia
市场调研
高级SEO、核心网页指标和聊天机器人自动化套件
使用GPT-4顾问、PageSpeed Insights和Slack提醒审核和监控SEO性能
If
Set
Cron
+12
22 节点Candra Reza
市场调研
工作流信息
难度等级
中级
节点数量10
分类1
节点类型6
作者
WeblineIndia
@weblineindiaA Leading Software Engineering, Consulting & Outsourcing Services Company in USA & India serving Clients Globally since 1999.
外部链接
在 n8n.io 查看 →
分享此工作流