mcpField
G
google-chat-messages

google-chat-messages

github.com/jezweb生产力1.1k1.3k 次安装3 周前更新
代码仓库

关于 google-chat-messages

google-chat-messages 是通过 Google Chat 入站 Webhook 发送消息的技能,适用于通知和结构化更新。它支持文本、cardsV2 卡片和带线程的回复,并提供 TypeScript 构建与发送工具。

主要功能

  1. 01发送格式化文本消息
  2. 02构建 cardsV2 富卡片
  3. 03发送线程回复
  4. 04使用 TypeScript Webhook 工具

适用场景

  1. 01发布部署状态通知
  2. 02发送每周摘要卡片
  3. 03在同一线程中更新告警

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/jezweb/claude-skills --skill google-chat-messages

安装后在 Claude Code 中输入/google-chat-messages确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

assets/
card-builder.ts
types.ts
webhook-sender.ts

详细介绍

Google Chat 消息

通过传入 Webhook 向 Google Chat 空间发送消息。可生成文本消息、富卡片(cardsV2)和线程回复。

可生成内容

  • 带有 Google Chat 格式的文本消息
  • 富卡片消息(cardsV2),包含标题、分区和组件
  • 线程对话
  • 可复用的 Webhook 发送工具

工作流

步骤 1:获取 Webhook URL

在 Google Chat 中:

  1. 打开一个空间 > 点击空间名称 > 管理 Webhook
  2. 创建 Webhook(为其命名,可选添加头像 URL)
  3. 复制 Webhook URL

将 URL 存储为环境变量或保存在密钥管理器中,切勿硬编码。

步骤 2:选择消息类型
需求类型复杂度
简单通知文本消息低
结构化信息(状态、摘要)卡片消息(cardsV2)中
持续更新线程回复中
操作按钮(打开 URL)带 buttonList 的卡片中
步骤 3:发送消息

使用 assets/webhook-sender.ts 作为发送工具。使用 assets/card-builder.ts 构建结构化卡片。

文本格式

Google Chat 不使用标准 Markdown。

格式语法示例
粗体*text**important*
斜体_text__emphasis_
删除线~text~~removed~
等宽文本`text``code`
代码块```text```多行代码
链接<url|text><https://example.com|Click here>
提及用户<users/USER_ID><users/123456>
提及所有人<users/all><users/all>

不支持:**双星号**、标题(###)、引用块、表格、内嵌图片。

文本消息示例
await sendText(webhookUrl, '*Build Complete*\n\nBranch: `main`\nStatus: Passed\n<https://ci.example.com/123|View Build>');

cardsV2 结构

卡片使用 cardsV2 格式(推荐使用,而非旧版卡片)。

const message = {
  cardsV2: [{
    cardId: 'unique-id',
    card: {
      header: {
        title: 'Card Title',
        subtitle: 'Optional subtitle',
        imageUrl: 'https://example.com/icon.png',
        imageType: 'CIRCLE'  // or 'SQUARE'
      },
      sections: [{
        header: 'Section Title',  // optional
        widgets: [
          // widgets go here
        ]
      }]
    }
  }]
};

组件参考

cardsV2 分区中提供的所有组件类型。

textParagraph

格式化文本块。支持 Google Chat 格式(*粗体*、_斜体_、<url|text>)。

{
  textParagraph: {
    text: '*Status*: All systems operational\n_Last checked_: 5 minutes ago'
  }
}
decoratedText

带可选图标的标签值。用于键值数据的最通用组件。

基本用法:

{
  decoratedText: {
    topLabel: 'Environment',
    text: 'Production',
    bottomLabel: 'Last deployed 2h ago'
  }
}

带起始图标:

{
  decoratedText: {
    topLabel: 'Status',
    text: 'Healthy',
    startIcon: { knownIcon: 'STAR' }
  }
}

带自定义图标 URL:

{
  decoratedText: {
    topLabel: 'GitHub',
    text: 'PR #142 merged',
    startIcon: {
      iconUrl: 'https://github.githubassets.com/favicons/favicon.svg',
      altText: 'GitHub'
    }
  }
}

带按钮:

{
  decoratedText: {
    topLabel: 'Alert',
    text: 'CPU at 95%',
    button: {
      text: 'View',
      onClick: { openLink: { url: 'https://monitoring.example.com' } }
    }
  }
}

可点击(整个组件):

{
  decoratedText: {
    text: 'View full report',
    wrapText: true,
    onClick: { openLink: { url: 'https://reports.example.com' } }
  }
}

带换行文本:

{
  decoratedText: {
    topLabel: 'Description',
    text: 'This is a longer description that should wrap to multiple lines instead of being truncated',
    wrapText: true
  }
}
buttonList

一个或多个操作按钮。按钮可打开 URL 或触发操作。

单个按钮:

{
  buttonList: {
    buttons: [{
      text: 'Open Dashboard',
      onClick: { openLink: { url: 'https://dashboard.example.com' } }
    }]
  }
}

多个按钮:

{
  buttonList: {
    buttons: [
      {
        text: 'Approve',
        onClick: { openLink: { url: 'https://app.example.com/approve/123' } },
        color: { red: 0, green: 0.5, blue: 0, alpha: 1 }
      },
      {
        text: 'Reject',
        onClick: { openLink: { url: 'https://app.example.com/reject/123' } }
      }
    ]
  }
}

带图标的按钮:

{
  buttonList: {
    buttons: [{
      text: 'View on GitHub',
      icon: { knownIcon: 'BOOKMARK' },
      onClick: { openLink: { url: 'https://github.com/org/repo/pull/42' } }
    }]
  }
}
image

独立的图片组件。

{
  image: {
    imageUrl: 'https://example.com/chart.png',
    altText: 'Monthly usage chart'
  }
}
divider

用于分隔组件的水平线。

{ divider: {} }
可折叠分区

可将分区设为可折叠,仅显示前 N 个组件:

{
  header: 'Details',
  collapsible: true,
  uncollapsibleWidgetsCount: 2,  // Show first 2, collapse rest
  widgets: [
    { decoratedText: { topLabel: 'Status', text: 'Active' } },
    { decoratedText: { topLabel: 'Region', text: 'AU' } },
    // These start collapsed
    { decoratedText: { topLabel: 'Instance', text: 'prod-01' } },
    { decoratedText: { topLabel: 'Memory', text: '2.1 GB' } },
    { decoratedText: { topLabel: 'CPU', text: '45%' } }
  ]
}

已知图标

decoratedText 和按钮组件可通过 knownIcon 使用的图标。

{ startIcon: { knownIcon: 'STAR' } }
// or
{ icon: { knownIcon: 'EMAIL' } }
图标名称用途
AIRPLANE旅行、航班
BOOKMARK保存、参考、链接
BUS交通、公共交通
CAR驾驶、交通
CLOCK时间、时长、日程
CONFIRMATION_NUMBER_ICON门票、预订
DESCRIPTION文档、文件
DOLLAR金钱、定价、费用
EMAIL电子邮件、消息
INVITE邀请
MAP_PIN位置、地址
MEMBERSHIP成员、用户
MULTIPLE_PEOPLE团队、群组
OFFER优惠、促销
PERSON个人用户
PHONE电话号码、通话
SHOPPING_CART商业、购物
STAR评分、收藏、重要事项
STORE商店、零售
TICKET门票、活动
VIDEO_CAMERA视频、会议

对于列表中没有的图标,可将 iconUrl 与任何可公开访问的图片搭配使用(正方形,建议尺寸为 24x24 或 48x48 像素)。

线程

使用 threadKey 将消息串联成线程:

// First message — creates thread
const response = await sendCard(webhookUrl, card, {
  threadKey: 'deploy-2026-02-16'
});

// Reply to thread — append &messageReplyOption=REPLY_MESSAGE_FALLBACK_TO_NEW_THREAD
const threadUrl = `${webhookUrl}&messageReplyOption=REPLY_MESSAGE_FALLBACK_TO_NEW_THREAD`;
await sendCard(threadUrl, replyCard, {
  threadKey: 'deploy-2026-02-16'
});

threadKey 是由客户端分配的字符串。相关消息应使用一致的键(例如 deploy-{date}、alert-{id})。

常见模式

通知卡片
import { buildCard, sendCard } from './assets/card-builder';
import { sendWebhook } from './assets/webhook-sender';

const card = buildCard({
  cardId: 'deploy-notification',
  title: 'Deployment Complete',
  subtitle: 'production - v2.1.0',
  imageUrl: 'https://example.com/your-icon.png',
  sections: [{
    widgets: [
      { decoratedText: { topLabel: 'Environment', text: 'Production' } },
      { decoratedText: { topLabel: 'Version', text: 'v2.1.0' } },
      { decoratedText: { topLabel: 'Status', text: '*Healthy*', startIcon: { knownIcon: 'STAR' } } },
      { buttonList: { buttons: [{ text: 'View Deployment', onClick: { openLink: { url: 'https://dash.example.com' } } }] } }
    ]
  }]
});
摘要卡片(每周总结)
const digest = buildCard({
  cardId: 'weekly-digest',
  title: 'Weekly Summary',
  subtitle: `${count} updates this week`,
  sections: [
    {
      header: 'Highlights',
      widgets: items.map(item => ({
        decoratedText: { text: item.title, bottomLabel: item.date }
      }))
    },
    {
      widgets: [{
        buttonList: {
          buttons: [{ text: 'View All', onClick: { openLink: { url: dashboardUrl } } }]
        }
      }]
    }
  ]
});

错误预防

错误修复方法
文本中使用 **bold**使用 *bold*(单个星号)
使用 [text](url) 链接使用 <url|text> 格式
缺少 cardsV2 封装将卡片封装在 { cardsV2: [{ cardId, card }] } 中
线程回复未进入线程将 &messageReplyOption=REPLY_MESSAGE_FALLBACK_TO_NEW_THREAD 附加到 webhook URL
Webhook 返回 400检查 JSON 结构——常见问题是顶层缺少 text 或 cardsV2
卡片未显示确保 sections 至少包含一个 widget

资源文件

文件用途
assets/types.tscardsV2 的 TypeScript 类型定义
assets/card-builder.ts用于构建卡片消息的实用工具
assets/webhook-sender.ts向 webhook 发送 POST 请求并处理错误

评论

支持 Markdown