AI PLAY玩法更新持续收录
← 回到更新流

2026-10-05 · 原文发布日

用Telegram问一句就查到日历空档

这个免费n8n模板把Telegram变成查空档助手:发文字或语音,语音先经OpenAI转写,再解析出日期范围、偏好的时间段和最短时长,然后调用Google Calendar的FreeBusy接口取忙碌时段,合并、相减、过滤掉太短的空档,按天分组回复到Telegram,并在Google Sheets记录每次查询。时区等参数可在配置节点改。适合经常被人问“什么时候有空”的人。

原文要点

该n8n模板把Telegram变成查空档助手:Telegram Trigger收文字或语音,语音先下载并用OpenAI转写;随后把消息归一化为chat ID、语言和请求文本,先回一条「正在查找」;再用OpenAI把请求解析成有边界的日期范围、按Europe/Berlin时区的偏好时间段和最短空档时长;调Google Calendar FreeBusy接口取忙碌区间,合并重叠后从各请求窗口中扣除,过滤掉短于下限和已过去的空档,按天和时段分组回复Telegram,并把每次查询追加到Google Sheets的calendar_availability页。时区、默认时段、最短时长、兜底chat ID都在Config节点改。

这次做成什么

搭好「发一句话(或语音)→解析意图→FreeBusy查忙碌→算出空档→回复并留痕」的链路,并用本站设计的一条虚构请求和一份虚构忙碌日历手工演算空档合并与过滤,验证算法输出与期望一致。

准备什么

  • 在@BotFather创建好的Telegram机器人token及n8n Telegram凭据
  • OpenAI API凭据(用于语音转写和请求解析,会产生费用)
  • Google Calendar OAuth凭据及一个可读取的日历
  • Google Sheets OAuth凭据及名为calendar_availability的标签页
  • 可接收Telegram webhook的n8n实例(自托管需公网地址)

具体怎么做

  1. 配Config与建表

    建Google Sheet,标签页命名calendar_availability,表头设为log_id、chat_id、language、request_text、date_from、date_to、windows、min_minutes、slots_found、logged_at十列。n8n里放一个Set节点命名Config,字段:timezone=Asia/Shanghai(原模板默认Europe/Berlin,按自己改)、default_windows=09:00-12:00,14:00-18:00、min_slot_minutes=30、fallback_chat_id=你的chat ID。

  2. 接消息与语音转写

    加Telegram Trigger;后接Switch:消息含voice则调Telegram下载语音文件,送OpenAI语音转写节点拿到文本;纯文本直接通过。汇合后用Set归一化为chat_id、language、text三个字段,并立即用Telegram节点回一句「好的,正在帮你查空档…」,避免用户干等。

  3. 解析请求为结构化参数

    调OpenAI聊天节点,用下方提示词把自然语言解析成JSON:date_from、date_to、windows(数组)、min_minutes,全部基于Config的timezone,「今天/明天」相对当前日期展开。解析失败或日期范围超过31天时回复用户换个说法,不要带着空参数去查日历。

  4. FreeBusy取忙碌并算空档

    用HTTP Request节点调Google Calendar的FreeBusy接口(POST https://www.googleapis.com/calendar/v3/freeBusy,body含timeMin、timeMax、timeZone和items:[{id:日历ID}])。返回busy区间后用一个Code节点:先按开始时间排序并合并重叠区间;再对每一天的每个窗口,用合并后的忙碌段依次切割出空闲段;丢弃早于当前时刻和短于min_minutes的段。

  5. 回复与留痕

    把空档按天分组、每天内按窗口分组排成多行文本(格式见下方示例output),Telegram节点发回chat_id;再Google Sheets节点向calendar_availability追加一行日志。找不到空档时也要明确回复「这段时间没有符合要求的空档」并同样记录。

可直接复制的材料

请求解析提示词

本站独立编写;{now}等占位由前面的节点注入,避免模型自己猜当前日期。

你把用户的日程查询请求解析成JSON。当前时间是{now},时区{timezone},用户消息:「{text}」。
只输出一个JSON对象:{"date_from":"YYYY-MM-DD","date_to":"YYYY-MM-DD","windows":["HH:MM-HH:MM"],"min_minutes":整数}
规则:「下午」=13:00-18:00,「上午」=09:00-12:00,「工作日」排除周末;用户没说时间段就用{default_windows};没说最短时长就用{min_slot_minutes};date_to最多比date_from晚31天;请求无法解析时输出{"error":"原因简述"}。

calendar_availability表头与测试日志CSV

本站合成测试行,chat_id为虚构值,验证留痕字段齐全。

log_id,chat_id,language,request_text,date_from,date_to,windows,min_minutes,slots_found,logged_at
LOG-0001,123456789,zh,明天下午有没有一小时的空,2026-10-07,2026-10-07,"13:00-18:00",60,2,2026-10-06T21:30:00+08:00

Config节点示例配置

本站设计的独立示例配置;原模板默认时区为Europe/Berlin,fallback_chat_id换成你自己的Telegram chat ID。

{
  "timezone": "Asia/Shanghai",
  "default_windows": "09:00-12:00,14:00-18:00",
  "min_slot_minutes": 30,
  "fallback_chat_id": "123456789",
  "max_range_days": 31
}

输入与输出示例

本站虚构演示,非真实调用结果;2026-10-07的星期标注仅为排版示意。

输入

10月6日晚发消息「明天下午有没有一小时的空」。虚构日历10月7日忙碌段:13:30-14:00、15:00-16:15、16:30-17:00;解析结果date_from=date_to=2026-10-07、windows=[13:00-18:00]、min_minutes=60。

对应输出

合并后忙碌段不变(无重叠)。从13:00-18:00扣除后得空闲段13:00-13:30(30分钟,丢弃)、14:00-15:00(60分钟)、16:15-16:30(15分钟,丢弃)、17:00-18:00(60分钟)。Telegram回复:
10月7日(周三)
· 14:00–15:00(60分钟)
· 17:00–18:00(60分钟)
并在calendar_availability追加一行slots_found=2的日志。

做完检查这些

  • 发送「明天下午有没有一小时的空」后先收到一条确认回复,随后收到按天分组的空档列表
  • 30分钟的空档在min_minutes=60时被正确过滤不出现在回复里
  • calendar_availability页每次查询恰好新增一行,date范围与请求一致
  • 发一段10秒语音说同样的话,转写后得到的空档结果与文字版一致
  • 请求超过31天范围时收到提示而不是错误的日历查询

容易卡住的地方

  • Telegram Trigger需要n8n有公网可达地址,纯localhost收不到更新,自托管要配webhook URL或tunnel
  • 「明天」这类相对日期依赖注入的当前时间,模型自己推算容易在跨时区凌晨出错,必须把now显式写进提示词
  • FreeBusy的timeMin/timeMax要带时区偏移,Config时区改了而请求体没跟着改会查出错位的忙碌段
  • OpenAI转写与解析都按调用计费,语音消息双重调用,高频使用要留意账单
  • Google Calendar OAuth授权的是「可读忙碌信息」即可,不要图省事给完整读写权限
  • 最短时长过滤放在切割之后做,先过滤再切割会把可用空档切碎

原文与作者资料 ↗

本站借助AI整理来源事实,独立编写中文操作指南与示例。示例不代表实际运行结果;来源效果尚未由本站独立复现。付费模板与模型、服务费用分别计算。

原文标题
Find free calendar slots from Telegram using Google Calendar, OpenAI and Sheets
原作者
Friedrich Bremer
原始发布日期
2026-10-05T15:05:28.709Z
来源
https://n8n.io/workflows/20471