GAS Slack Bot Skill 面向需要在 Google Apps Script 上搭建无服务器 Slack 机器人的场景,目标是把 Google 侧与 Slack 控制台的配置一次性走完,最后在目标频道完成实测。
适用场景
- 用户希望基于 Google Apps Script 构建 Slack 机器人。
- 任务包含 Apps Script 侧的项目创建与代码配置。
- 任务包含 Slack App 创建、权限作用域、事件订阅或安装。
- 工作流需要复用已登录的 Google 或 Slack 会话。 使用前应先通过 logged-in-google-chrome-skill 建立浏览器会话。
默认产出
- 目标机器人仓库,包含 Code.js、appsscript.json、package.json、.clasp.json.example、.env.example、.gitignore,以及可选的 README.md。
- 已部署的 Apps Script Web App URL。
- 已安装到目标工作区的 Slack App。
- 已验证的 Event Subscriptions,包含 message.channels。
- 在目标 Slack 频道的最终实测。
快速开始
- 用 scripts/scaffold_gas_slack_bot.ps1 生成目标仓库。
- 在开始浏览器操作前,将 .env.example 复制为 .env。
- 用 logged-in-google-chrome-skill 启动或复用专用 Chrome 配置。
- 在 js_repl 中通过 CDP 附加 Playwright。
- 创建或打开 Apps Script 项目并填入 GAS 代码。
- 创建 Slack App、添加作用域并安装。
- 设置 Apps Script 的 Script Properties。
- 将 GAS 项目部署为 Web App。
- 优先使用 Slack App Manifest 锁定 request_url 与 message.channels。
- 邀请机器人进入目标频道,并确认实时回声回复。
脚手架命令示例
powershell -ExecutionPolicy Bypass -File .\scripts\scaffold_gas_slack_bot.ps1 -TargetRepoPath D:\Prj\my-slack-bot
-BotName "Slack Parrot Bot" -TeamId T0AL9FZTL72
-ChannelId C0AJZQJCVTR
脚本会从 assets/templates/ 复制模板并替换占位符。生成后立即把 .env.example 复制为 .env,并随着环境相关值的创建或发现持续填写。
浏览器工作流 使用 $logged-in-google-chrome 之后,通过当前工作区的 playwright-core 或 playwright 附加: var chromium; var browser; var context; var page; { const nm = await import("node:module"); const requireForPw = nm.createRequire("file:///D:/Prj/some-workspace/package.json"); ({ chromium } = requireForPw("playwright-core")); browser = await chromium.connectOverCDP("http://127.0.0.1:9222"); context = browser.contexts()[0]; page = context.pages()[0]; } 在整个配置过程中保持同一附加浏览器存活。
工作流细节
- 先构建本地仓库:脚手架或修改现有文件;密钥不入库;使用 Script Properties 存令牌和环境值;立即复制 .env 并把它当作目标环境的持久运行日志,记录 Slack ID、令牌、Apps Script ID、部署 ID 和最终 Web App URL;.env 不进 git,.env.example 仅保留占位符。模板位于 assets/templates/ 下的 Code.js、appsscript.json、.env.example、package.json、slack-app-manifest.json、slack-app-manifest.gemini.json、script-properties-bootstrap.js。
- 创建 Apps Script 项目:若首页界面不稳定,优先用 https://script.new;尽早重命名项目;若编辑器为 Monaco,优先直接更新模型而非点击;打开项目设置前先保存。
- 创建 Slack App:除非明确指定现有应用,否则从零创建;至少添加 chat:write、channels:history;使用令牌前先安装到目标工作区;将元数据写回 .env,尤其是 SLACK_TEAM_ID、SLACK_ALLOWED_CHANNEL_ID、SLACK_API_APP_ID、可选的 SLACK_CLIENT_ID 及配置过程中出现的令牌。
- 设置 Script Properties:至少包含 SLACK_BOT_TOKEN、SLACK_VERIFICATION_TOKEN、SLACK_ALLOWED_CHANNEL_ID、SLACK_TEAM_ID、SLACK_API_APP_ID,尽量从 .env 取值。
- 部署 Apps Script:部署为 Web app,以当前 Google 账号执行,访问权限设为 Anyone 以便接收 Slack 事件;将脚本 ID、部署 ID 与 /exec URL 记入 .env,并在回到 Slack 前验证 doGet()。
- 配置 Slack 事件:优先用 App Manifest 做最终持久配置,使用 assets/templates/slack-app-manifest.json 并设置 settings.event_subscriptions.request_url 与 settings.event_subscriptions.bot_events = ["message.channels"];若 URL 未验证,触发内置验证流程,直到显示 Enable Events: On、Request URL Verified、message.channels。
- 最终验证:邀请机器人入目标频道,发一条唯一测试消息,确认同一文本由机器人返回。
默认实现要点 模板使用 verification-token 载荷校验,因为 Apps Script Web App 不以便于使用的方式暴露 Slack 签名头;通过 CacheService 按 event_id 去重;忽略机器人消息与子类型事件;存在 thread_ts 时在线程内回复。
参考文档 完整配置顺序与理由见 references/end-to-end-flow.md;界面自动化或验证卡住时见 references/blockers-and-workarounds.md;机器人需要调用 Gemini 或处理 Slack 附件时见 references/gemini-multimodal-bot.md;具体经验见 references/case-study-gas-slack-bot-gemini.md。
变体说明 简单回声或命令机器人保持默认模板精简。需要分析附件或调用 Gemini 时:从 references/gemini-multimodal-bot.md 开始;复用 assets/templates/slack-app-manifest.gemini.json 以启用 files:read 与 file_shared;若 Script Properties 界面阻碍自动化,临时插入并运行 assets/templates/script-properties-bootstrap.js,再恢复最终生产代码;文件事件可能同时经 message.channels 与 file_shared 到达时,先用 CacheService 加 LockService 认领一次文件响应再回复。
限制与约束 密钥不得存入仓库;不提交 .env,只跟踪 .env.example;不假设 Slack 界面稳定,重载后需验证;不单凭视觉判断,保存或重载后确认值已持久化;不直接调用 Python,需用 uv run 运行 Python 辅助脚本;Slack 界面不可靠时改用 App Manifest;首次部署遇到 Google 未验证应用警告时需按流程处理并继续。