☰
AI编程实践:用Gemini 3.0搭建短信到滴答清单的自动化桥接
2026/9/30 7:40:00 网站建设 项目流程

1. 为什么我会想干这件事:短信和滴答清单之间的“最后一公里”

1.1 一个让我崩溃的场景

先说个真实场景。我手机常年静音,微信、企业IM、邮件全都靠滴答清单来兜底,唯独短信这玩意儿一直游离在体系之外。运营商验证码、银行动账通知、快递柜取件码、客户临时改时间的短信……每一条都有时效性,错过就是麻烦。有一天我因为没看到一条“下午三点会议室变更”的短信,抱着笔记本在旧会议室傻等了半小时。那一刻我真想把短信直接变成滴答清单里的一个任务,到点提醒我处理。

这个需求一点都不复杂:来一条短信,自动在滴答清单里建一个任务,内容包含发件人和短信原文,带上截止时间或标签。但真要手动实现,又涉及安卓端的短信监听、HTTP回调、第三方开放API的鉴权、去重逻辑,怎么想都觉得不值当。直到我开始用 AI 编程的方式干活,用 Gemini 3.0 来写中间这一层胶水代码,事情才变得可行。

1.2 为什么不用现成工具

市面上当然有 IFTTT、Tasker、Automate 这类自动化工具。我也试过,但始终没长期用起来,原因很实在:

  • 大部分自动化工具对短信的读取权限限制很严,尤其在 Android 高版本上,第三方应用拿不到全部短信内容。
  • 滴答清单的官方 API 开放能力很强,但第三方自动化平台的封装层往往只暴露“新建任务”这种粗粒度动作,没法灵活设置标签、优先级、提醒时间。
  • 免费方案不稳定,付费方案按量计费,为了一个个人小工具长期订阅,肉疼。

所以绕了一圈,最靠谱的路线是自己搭一个中间服务:短信转发器负责把短信变成 HTTP 请求,中间服务负责解析内容,再调用滴答清单的开放接口建任务。这正好也是 AI 编程最擅长的场景——不涉及复杂算法,纯粹是接口胶水、数据转换、异常处理。

1.3 “说人话”指挥 Gemini 3.0 这事靠不靠谱

我必须诚实说,接这个项目之前我半信半疑。Gemini 3.0 这类大模型生成个冒泡排序、写个响应式页面,大家都见多了。但要完成“短信系统到滴答清单接口的桥接”,涉及手机端配置、服务端接口、第三方 API 鉴权、生产环境部署,AI 真能一步到位?

实际体验下来,结论是:能,但有前提。前提是你得把需求讲得像跟一个脾气不太好但技术很硬的同事沟通一样——边界清晰、输入输出明确、异常情况说清楚。这也是为什么我强调“说人话”而不是“说黑话”。不需要堆术语,但得把业务逻辑讲明白。Gemini 3.0 对这种事务型代码的理解能力比我预期强很多,尤其擅长把“描述性的流程”直接转换成“可运行的代码骨架”。

2. 先把链路和技术方案定下来:接口不是写代码,是划边界

2.1 整条链路的架构设计

项目动手前,我先在纸上画了一条链路,总共四段:

安卓手机短信 → 短信转发器 → 自建中间服务 → 滴答清单 OpenAPI

这个图不需要多高级,理解成“消息从左流到右”就行。短信进来后,转发器截获内容,用 POST 请求推给我的服务器;服务器收到后做一次解析和去重,再调用滴答清单的接口创建任务。中间服务是我唯一需要写代码的部分,也是整个项目的核心。

选择这个结构有几个原因。第一,它把手机端和服务端解耦,以后换手机、换转发器都不影响服务端逻辑。第二,所有调试都可以在电脑上完成,不用反复折腾手机日志。第三,中间服务以后还能挂载更多自动化逻辑,不局限于短信。

2.2 短信侧:转发器怎么把短信变成 HTTP 请求

手机端我选的是开源项目 SMS Forwarder,也就是常说的“短信转发器”。它在 Android 上监听系统短信数据库变化,并通过规则匹配把短信内容转发到指定 URL。配置时有几个关键参数:

  • 接收号码:用正则匹配,比如只处理非 106 开头的号码,避免垃圾短信涌入。
  • 请求方式:POST,JSON 格式,方便服务端解析。
  • 请求体:包含 sender、content、date 三个字段,足够覆盖后续所有逻辑。

这里有个容易忽略的细节:转发器发出去的请求,服务端无法确认它是否真的收到了短信,所以必须在服务端做“收到即确认”,返回 200。如果转发器没收到 200,就会按自己的重试策略再推一次。这个行为既是好事也是麻烦,后面我会单开一节讲幂等性。

2.3 滴答清单侧:OpenAPI 的接口约定

滴答清单的开放接口,网上资料不少,最核心的就是创建任务的接口。它用的是 OAuth2 鉴权,先拿到 access_token 和 refresh_token。实际调用时,直接往任务列表接口 POST 一组 JSON 字段,包括 title、content、tags、dueDate、priority 这些。

官方文档写得比较规范,但我第一次看的时候愣是没找到“项目 ID”是从哪获取的。其实很简单:调用项目列表接口,就能拿到当前账号下所有项目及其 ID。把那个 ID 填到请求里,任务就会落到指定的清单目录。

这个环节是“接口定义”的部分。你需要明确定义:中间服务接收的短信格式是什么,输出给滴答清单的任务字段是什么。就像订合同一样,先把甲乙方边界说清楚。

2.4 中间这层“翻译接口”如何设计

我把中间服务定义成一个极简的 Webhook 接收器,只暴露一个路由:

POST /api/sms

请求体示例:

{ "sender": "10086", "content": "您的话费余额已不足10元,请及时充值。", "date": "2026-05-18 10:24:00", "sms_id": "abc123" }

服务端拿到这个请求后,做三件事:

  1. 查一下 sms_id 有没有处理过,处理过就直接返回 200,不重复建任务。
  2. 把 sender 和 content 拼成滴答清单的任务标题或备注,设置一个标签,比如“短信”。
  3. 调用滴答清单接口创建任务,成功返回 200,失败则返回 502 并让转发器触发重试。

这里的 sms_id 是我特意要求 Gemini 3.0 加上的。一条短信每转发一次,该 ID 保持不变,后续重复请求再频繁也不会导致任务重复。这也是接口设计里常说的“幂等性控制”。你不可能要求第三方推送系统永远只推一次,但你的服务可以做到同一条消息只处理一次。

2.5 为什么不用更“重”的方案

有人可能会问,干嘛不直接在手机上加一个监听服务,或者直接用安卓的 BroadcastReceiver?我的答案很简单:个人项目最重要的是可维护性和可替换性。手机上的应用生态变化太快,今天能监听短信的权限,明天可能就被系统收紧。把短信转成 HTTP 请求之后,手机那边就变成了一个“传感器”,服务端才是真正的“大脑”。将来我甚至可以再加一个入口,让邮件、Slack 通知也走同一套中间服务。

用“服务器 + Webhook”的另一个好处是,Gemini 3.0 对这种模式非常熟。模型见过大量类似的 Webhook 接收代码,生成出来的代码质量很高,我只要做少量修改就能上线。

3. Gemini 3.0 实战:从一句人话到可以跑的代码

3.1 第一版提示词该怎么写

我踩过不少次提示词设计的坑,慢慢总结出一个靠谱的套路:不说术语,但把流程按“输入 → 处理 → 输出”讲清楚。以下是我实际发给 Gemini 3.0 的第一个版本:

我搭了一个短信转发器,它会向我的服务器 POST 一个 JSON,格式是: {"sender": "发件人号码", "content": "短信内容", "date": "短信时间", "sms_id": "唯一ID"} 请你写一个 FastAPI 服务,包含: 1. 一个路由 POST /api/sms,接收上面的 JSON; 2. 先把 sms_id 存到 SQLite 里,如果已经存在就直接返回 200; 3. 如果不存在,就调用滴答清单的创建任务接口,把 sender 和 content 拼接成任务标题,标签设置为“短信”,提醒时间设为10分钟后; 4. 滴答清单接口的鉴权信息用环境变量传入; 5. 如果创建失败,返回 502; 6. 日志要完整,把请求体和响应体都打出来。 请直接给出全部代码,包含 requirements.txt。

这段话没有任何高深词汇,但 Gemini 3.0 能准确理解“先把 sms_id 存到 SQLite 里”是什么意思。它生成的代码里还主动加了 CORS 中间件,虽然我这个场景其实用不上,但说明模型对 Web 服务的安全习惯有默认预期。

3.2 代码生成后,手动补哪些关键细节

AI 生成的代码骨架能跑,但距离“能放心用”还有几段路要走。我拿到第一版代码后,重点检查了四件事:

  • 环境变量:滴答清单的 client_id、client_secret、access_token、refresh_token 是否都从环境变量读取,没硬编码。
  • Token 刷新:滴答清单的 access_token 大概几小时就会过期,必须要有 refresh 逻辑。Gemini 3.0 生成的初始版本只写了读取 token,刷新逻辑是我追问后补上的。
  • 请求超时:外部 API 调用必须设置 timeout。如果不设置,滴答清单接口万一挂起,整个服务都会卡住。
  • 时区处理:滴答清单的 dueDate 用的是 UTC 时间,而短信时间通常是本地时间。我直接在代码里加了“所有时间统一转成 UTC + 换算到滴答清单所需格式”的一步。

这里要特别强调“检查依赖版本”。AI 生成的 requirements.txt 里可能写的是 FastAPI 最新版本,但你的服务器上如果已经装了旧版,启动就会报错。建议在项目里用虚拟环境,而不是直接丢到全局环境里。

3.3 端到端联调:curl 一下就知道通没通

写完代码先不开手机端,直接在电脑上模拟一条短信,这是最快验证链路的方式:

curl -X POST http://localhost:8000/api/sms \ -H "Content-Type: application/json" \ -d '{ "sender": "13800138000", "content": "项目评审改到明天下午3点,地点508会议室", "date": "2026-05-18 10:24:00", "sms_id": "test-001" }'

如果一切正常,滴答清单里会立刻出现一条任务,标题大概是“13800138000:项目评审改到明天下午3点,地点508会议室”,带“短信”标签,提醒时间在10分钟后。

第一次跑成功的时候,说实话还挺激动的。但紧接着我又用同一个 sms_id 再发了一次请求,返回 200 但没创建重复任务。这一步验证了幂等性,非常重要。很多新手做到“能跑”就停了,结果上线后被短信转发器自己的重试机制搞得任务泛滥。

3.4 用对话迭代修 Bug:把异常直接丢给 AI

联调过程中遇到一个奇怪问题:短信内容如果包含特殊字符,比如&、=,滴答清单建出来的任务标题会被截断。我一查日志,发现是转发器发来的请求里没有正确做 URL 编码,导致服务器解析 body 时把参数拆错了。

这种问题让我自己查,估计要翻半天文档。我的做法是把报错日志直接贴给 Gemini 3.0,然后补一句:“这个报文在服务端解析出来缺了后半截,你帮我判断是 URL 编码的问题还是请求体解析的问题,并给出修复方案。”它很快就指出短信转发器端用的是application/x-www-form-urlencoded格式,而我的 FastAPI 服务声明的是 JSON 类型,两边需求不匹配。最终我把服务端改成同时支持两种 content-type,问题当场解决。

AI 编程比较有价值的地方就在这里:它不只是生成代码,还能做“代码会诊”。只要你能把现象和日志描述清楚,它通常能给出靠谱的排查方向。

4. 这一路踩过的坑:短信重复、Token失效、时区错乱

4.1 短信重复推送导致的任务重复

这个坑几乎人人都会踩。短信转发器为了保证消息不丢,默认会做失败重发。如果服务器处理正常但网络抖动,导致响应没回到手机端,短信就会被再次推送。第一次我没做去重时,一个验证码短信给我建了五个任务。

解法就是我前面提到的 sms_id 去重。具体实现时,我给 SQLite 的表加了唯一索引:

CREATE TABLE IF NOT EXISTS processed_sms ( sms_id TEXT PRIMARY KEY, processed_at TEXT DEFAULT (datetime('now')) );

写入时用INSERT OR IGNORE,如果返回的 rowcount 为 0,说明以前处理过,直接返回 200 即可。我对 Gemini 3.0 补充了一个新需求:“加一个 processed_sms 表做去重,用 INSERT OR IGNORE”,它就自动把代码调整好了。这一步是接口幂等性的具体落地,看似简单,价值极高。

4.2 滴答清单 Token 刷新和 OAuth2 细节

滴答清单的 OpenAPI 用的是标准 OAuth2,凭据分两段:第一段拿 authorization code,第二段换 access_token 和 refresh_token。access_token 有效期短,但 refresh_token 有效期长。我用的是“刷新一次 token 后回存数据库”的方案。

实际操作时,Gemini 3.0 生成的刷新逻辑有一个隐患:它假设 refresh_token 永远有效。但如果长期不用,refresh_token 也会过期,届时必须重新走一遍授权流程。我加了一个文件标记,当刷新失败时,除了报错,还往手机推一条系统通知,提醒我手动去补授权。这条逻辑是我自己加的,AI 不会主动替你考虑“如果 refresh_token 也失效了怎么办”。

另外,滴答清单的 API 请求头必须写成Authorization: Bearer <token>,少个空格都会 401。我调试时被这个坑了近半小时,后来用--trace抓包才看出来。

4.3 时区和时间格式问题

滴答清单创建任务时,dueDate 参数要求是 ISO 8601 格式的 UTC 时间。比如北京时间的2026-05-18 15:00:00,要转成2026-05-18T07:00:00.000Z。这个转换如果做错,任务提醒会差八个小时。

我的解决方式很直接:在代码里统一约定“外部输入一律视为本地时间,程序里转换为 UTC”。这句话也被我写进了提示词:“所有时间字段统一按 UTC 存储,传给滴答清单前把格式转成 ISO 8601。”Gemini 3.0 对时区库的使用很熟练,直接用了 Python 的 zoneinfo,还自动生成了处理夏令时的逻辑。虽然国内用不上夏令时,但放到海外环境也能跑。

4.4 手机端权限和进程保活

短信转发器在 Android 高版本上跑得稳不稳,取决于两个权限:短信读取权限和通知权限。前者是核心,后者是进程被系统回收后重新唤醒的保障。

我最初只在手机上给了短信权限,结果偶尔出现“一条短信没被转发”的情况。排查后发现是系统杀掉了转发器的后台进程。后来我把转发器的电池优化策略改成“不限制”,并开启了通知权限,问题就基本消失了。这里想给一个忠告:手机端工具不要追求什么都自动,最好每隔几天打开一次 App 看看日志,确认转发还正常。

5. 常见问题排查速查表

5.1 五个典型故障和定位思路

我用一张表把这些天遇到的典型问题整理出来,方便你直接对着查。

现象可能原因定位方法
短信收到但滴答清单没任务转发器未启动或权限被回收打开转发器查看日志,确认 POST 请求是否发出
任务创建了但内容为空请求体解析失败看服务端日志里原始 request body,检查 content-type 是否匹配
重复任务出现缺少幂等处理检查 processed_sms 表,确认是否支持同 sms_id 去重
接口返回 401access_token 过期或未刷新调通 refresh 逻辑,检查环境变量里的凭据
提醒时间少了8小时时区转换错误检查是否统一转为 UTC,并按规定格式传 dueDate

排查这类问题,核心思路就一句话:先确认数据流到哪一步断了。从短信转发器的日志开始看,再到服务端日志,再到滴答清单侧的任务列表,逐段确认。千万别上来就查代码,大概率是前面的环节问题。

5.2 提示词微调的实测经验

Gemini 3.0 在生成代码上表现很好,但前提是提示词足够具体。我总结了几个能让它少出幺蛾子的表达方式:

  • 直接给样例数据。比如把转发器真实的 JSON 报文贴进去,模型生成的反序列化代码就会照着你的结构来,而不是自己发明字段。
  • 明确失败时的行为。我在提示词里加了“如果调用滴答清单失败,返回 502,并打印完整响应”,这个细节避免了服务端静默吞错。
  • 分步提需求,而不是一口气全塞。第一轮只让它写接收短信的逻辑,第二轮再让它加滴答清单调用,第三轮加去重。每轮都基于上一轮的结果继续,代码质量明显更高。
  • 把代码当产品迭代,而不是一次性交付。生成后用真实 curl 请求测,发现不对就贴日志回去继续问。整个项目我大概迭代了七八轮,每次改动都很小,基本没出现推翻重来的情况。

6. 扩展想法:这件事的门槛其实不在AI,在“定义边界”

6.1 把同一套模式复用到其他场景

这次打通短信和滴答清单之后,我意识到这套模式可以复制到很多地方。比如把邮件里带附件的通知转成任务、把公众号推送的关键内容转成任务、甚至把某个系统监控的 webhook 告警直接落到滴答清单里。核心思路都是一样的:源系统 → 标准化事件 → 中间处理服务 → 滴答清单 OpenAPI。中间处理服务可以攒出很多花样。

往大里说,这其实就是“事件驱动”思想的个人版实践。滴答清单是我的任务收件箱,短信、邮件、聊天记录都可以往里汇。AI 在这里的角色,像是一个翻译官,帮我把各种不兼容的接口协议变成我能看懂的清单条目。Gemini 3.0 对接口定义、幂等性、OAuth 这些概念的理解,比我想象中扎实,我只需要把控边界即可。

6.2 给也想试 AI 编程的朋友几句实话

最后说点掏心窝的话。AI 编程确实把开发门槛拉低了,但没低到“完全不用动脑”。实际做过一遍你会发现,AI 擅长的是把明确的需求转化成代码,而不是替你想清楚需求。你如果连自己都想不清楚“短信来了之后怎么处理、重复怎么办、失败怎么办”,那 AI 再强也帮不了你。

我现在的习惯是:拿到一个自动化需求,先花 10 分钟梳理输入、处理、输出、异常这四件事,再让 AI 写代码。顺序反过来的话,你会陷入无穷无尽的改写循环,甚至比手写还慢。再分享一个小技巧:上线之前,用带前缀的测试短信多跑几次,比如标题统一加“测试”字样,造假确认后手动清理掉,能避免把测试数据混进真实清单里。这是很多人没提过的细节,但对实际体验影响很大。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询