mcpField
S
send-message

send-message

github.com/terrylica生产力172 次安装今天更新
代码仓库

关于 send-message

send-message 是通过 MTProto 从个人 Telegram 账号发送消息的技能,涵盖授权检查、主题选择、HTML 格式、长消息拆分及编辑决策。

主要功能

  1. 01检查 Telegram 会话授权
  2. 02发送到指定群组主题
  3. 03使用 Telegram HTML 格式
  4. 04自动拆分长消息
  5. 05指导编辑与更正补充

适用场景

  1. 01在合适的群组主题发布更新
  2. 02发送含代码或标题的格式化消息
  3. 03将长内容拆分为连续消息
  4. 04避免静默改写已读消息

安装

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

$npx skills add https://github.com/terrylica/cc-skills --skill send-message

安装后在 Claude Code 中输入/send-message确认已加载。

详细介绍

发送 Telegram 消息

通过 MTProto 从你的个人 Telegram 账号(而非机器人)发送消息。

自进化技能:此技能会在使用过程中不断改进。如果说明有误、参数已变更,或需要采用变通方案,请立即修复此文件,不要拖延。仅在遇到真实、可复现的问题时才更新。

发送前检查

发送前,请确认会话已授权(不只是确认文件存在):

bun "$SCRIPT" check-auth

如果状态为 EXPIRED,请先运行 /tlg:setup(使用 3 步非交互式授权模式)。

超级群优先方法

Bruntwork 群组(-1003958083153)是一个带有话题的超级群。发送到此群组的所有消息都必须指定特定话题,绝不能直接发送到不带话题的超级群。

超级群优于普通聊天的原因:

  • 服务器全局消息 ID。 每位成员看到的每条消息都有相同的 id=N。双方的 Claude Code 都能以相同方式解析引用,无需查看者限定,也不会产生跨边界歧义。
  • 话题命名空间。 政策不会淹没在每日签到消息中。每个主题都有独立、可搜索的线程和置顶消息。
  • AI Agent 可寻址性。 Claude Code 可以通过 reply_to_msg_id 针对特定话题读取或发送消息,从而实现精确路由,例如“将此错误报告发送到 Bug Reports”或“在 Policies 中搜索关于例外条款的决策”。
  • 表情符号回应可用作确认信号。 可通过 message.reactions.results 以编程方式读取回应,从而轻松检查确认状态,无需对方回复文字。

话题选择规范: 撰写消息时,请从下方的话题注册表中选择最具体的话题。仅在没有更合适话题时才使用 General。绝不要将同一条消息发送到多个话题。

引用规范: 裸写的 id=N 引用对所有成员的解析结果都相同。引用之前的消息时,请注明其 ID。双方的 Claude Code 都可以通过 client.get_messages(supergroup_id, ids=N) 自行查找。

通过 tg-cli.ts 发送到话题: 使用 --reply-to 标志,并指定该话题的 root_msg_id。root_msg_id 的值请参见下方的话题注册表部分。

bun "$SCRIPT" send --html --reply-to 5 -1003958083153 "<b>Policy update</b> ..."

长消息自动拆分

Telegram 每条消息的硬性限制为解析后 4096 个字符。tg-cli.ts 的 send 和 draft 都会自动拆分超过约 3900 个纯文本字符的消息,生成多个依次发送的消息,同时保留 HTML 格式和章节结构。

拆分算法:在能够满足所有消息块长度限制的前提下,选择最细粒度的安全边界进行拆分:

  1. \n\n━━━━━━━━━━━━━━\n\n(主要章节分隔符,优先使用)
  2. \n━━━━━━━━━━━━━━\n(章节分隔符)
  3. \n\n(段落分隔符)
  4. \n(换行符)
  5. 按字符硬拆分(最后手段——会打印警告,且可能拆断标签)

每个续发消息块前都会添加 <i>(Part N/M)</i> 标题,让收件人清楚地看到消息顺序。所有部分都使用相同的 --reply-to 目标,确保多段消息保留在同一个话题线程中。

现在无需再手动拆分消息。 将完整 HTML 编写为一个字符串并传给 send,拆分器会自动处理。

按长度规划内容的建议:尽量让消息能够放在单条消息中(≤ 3900 个纯文本字符),因为拆分后会因部分标题而增加视觉负担。如果消息内容本身较长(例如置顶参考资料),就让拆分器处理。使用 ━━━━━━━━━━━━━━ 分隔章节,以便在逻辑章节之间整齐拆分。

用法:tg-cli.ts(会话有效时)

拿不准时,使用 --html。 如果你的消息包含以下任何内容:<b>、<i>、<code>、<pre>、<a href>、粗体标题、行内代码或 Markdown 风格的 **粗体** / `代码`,你必须传入 --html(并先将 Markdown 转换为 HTML 标签),或者去掉这些修饰。发送 Telegram 风格的 Markdown 时,如果不使用 --html,收件人看到的会是原样的星号和反引号。对于包含标题、分隔符和代码片段的多段消息,始终使用 --html。

如果已经发送了格式混乱的消息,可按以下模式补救:发送一条以 Correction — earlier message rendered as raw text, corrected version below: 开头的后续消息,然后附上正确使用 HTML 格式的内容。如果消息已被阅读,切勿悄悄编辑(见下文“编辑规范”)。

/usr/bin/env bash << 'SEND_EOF'
ROOT="$(cc-plugin-root tlg)"
SCRIPT="$ROOT/scripts/tg-cli.ts"

# Default: plain text (use only for single-line unformatted messages)
bun "$SCRIPT" send @username "Hello"

# HTML formatting — the recommended default for any structured message
bun "$SCRIPT" send --html -1003958083153 "<b>Bold header</b>

Body with <code>inline code</code> and <a href='https://example.com'>a link</a>."

# By chat ID (groups use negative IDs)
bun "$SCRIPT" send -1003958083153 "Hello group"

# Specific profile
bun "$SCRIPT" -p personal send @username "Hello"

# Edit a message by ID
bun "$SCRIPT" edit -1003958083153 12345 "<b>Updated text</b>"

# Delete a message by ID
bun "$SCRIPT" delete -1003958083153 12345
SEND_EOF

较长的 HTML 消息:tg-cli.ts send --html 会在达到 3900 个纯文本字符的阈值时自动拆分。将完整 HTML 写成一个字符串,让拆分器处理。参见上文“长消息的自动拆分”。

编辑规范——未读与已读

核心原则:只有当你确信收件人尚未阅读消息时,才悄悄编辑。有人看过消息后再编辑,可能会造成错误记录并引起困惑(他们记得原文,但聊天中现在显示的是不同内容)。

情况操作
你在不到 30 秒前于活跃的异步聊天中发送了消息,且期间没有人操作 Telegram可以安全编辑——可自由迭代
你刚发送的消息有错别字或事实错误,且收件人尚未回复可以安全编辑——他们很可能还没看过
收件人已回复你的消息切勿悄悄编辑——发送补充
收件人已读消息但尚未回复(你看到已读回执,或他们的输入状态提示出现后又消失)切勿悄悄编辑——发送补充
你不确定收件人是否已读默认发送补充——这样更不容易造成困惑
聊天中的其他人已引用该消息切勿编辑——引用内容现在已成为过时上下文;应改为发送补充

补充消息模式(编辑不安全时):

Correction on my previous message: <specific change>

或

Update to what I said above: <new info that supersedes>

补充消息应当自成一体,让回看聊天记录的读者无需交叉参照也能理解。

为何这很重要:悄悄编辑已读消息是聊天系统中最令人困惑的用户体验反模式之一。收件人记得“特里告诉我 X”,现在却看到“X'”,于是会怀疑是自己记错了,还是有人在操纵他们。编辑应当在对方看到消息之前使用,而不是用来篡改历史记录。

如何判断消息是否已读:Telegram 的 MTProto 会通过 messages.readHistoryOutbox 更新,在一对一和小型群聊中提供已读回执,但在大型群聊中并不可靠。最稳妥的判断方法是结合时间和活跃情况:如果已过去约 60 秒以上,和/或收件人曾在聊天中活跃,就假设他们已经看过消息。

Telegram HTML 格式参考

GramJS 使用 HTML,而非 Markdown:

标签渲染效果
<b>text</b>粗体
<i>text</i>斜体
<u>text</u>下划线
<s>text</s>删除线
<code>text</code>Inline code
<pre>text</pre>代码块
<a href="url">text</a>超链接
<tg-spoiler>text</tg-spoiler>剧透内容
水平分隔线规则(强制约定)

在较长消息的各个部分之间使用 ━(U+2501)作为水平分隔线。

长度规则:建议使用 14 个字符,绝对上限为 22 个字符。

  • 建议长度:━━━━━━━━━━━━━━(14 个 ━)
  • 可接受上限:━━━━━━━━━━━━━━━━━━━━━━(22 个 ━,= 14 + 8)
  • 切勿超过 22 个字符——较长的分隔线在移动客户端上看起来不平衡,还会使正文内容超出屏幕。

原因:Telegram 移动客户端会重新排布正文,但不会换行显示由制表符画线字符组成的分隔线。在窄屏手机上,28 个字符的分隔线会导致水平滚动;14 个字符的分隔线可在所有视口中清晰显示,并仍能起到明确的分隔作用。如果需要更醒目的视觉效果,请在分隔线前使用标题(<b>...</b>),而不是加长分隔线。

支持表情符号,但用户可能更喜欢不带表情符号的装饰——请改用 <pre> 块和制表符画线字符。

配置文件

配置文件账号用户 ID
work (default)@ExampleOpsAccount
personal@personal_account

已知群聊 ID

群组聊天 ID类型
Terry & MD (Bruntwork)-1003958083153超级群组
Terry & MD (Bruntwork)-1003958083153旧版基础群聊(2026-04-16 之前,旧消息只读)

话题注册表(Bruntwork 超级群组)

若要向特定话题发送消息,请在 send_message() 中传入 reply_to=<root_msg_id>,或在 tg-cli.ts 中使用 --reply-to。

话题root_msg_id范围
常规1通用事项、快速提问
任务与交付物2任务定义、PR 审查、Block 签到
日常运营3入职/离职、轮班状态
入职与访问4仓库访问权限、SSH/Tailscale、工具配置
政策与标准5cc-skills 例外条款、约定、纪律
Bug 报告与事故6合并冲突、钩子 Bug、流水线故障
工具设置与配置7example-service、example-app、example-pipeline
知识库与学习8知识库页面、研究材料、技能参考
人力资源与排班9轮班时长、Bruntwork 协调
会话监控185Claude Code 会话实时摘要(CC Nasim Bot)

反模式(绝不可这样做)

反模式失败原因
未先检查身份验证就运行 bun "$SCRIPT"如果会话已过期,身份验证会失败
预检时只检查会话文件是否存在会话文件可能存在但已过期——必须使用 check-auth 检查
使用纯文本发送格式化消息GramJS 使用 HTML,而不是 Markdown。使用 --html 标志进行格式化

错误处理

错误原因修复
Unknown profile-p 值无效使用 work 或 personal
Cannot find any entity用户名或 ID 无效使用 dialogs 命令验证,或使用 find-user 解析
message cannot be empty传入了空字符串提供消息文本
Session expired会话不再有效运行 /tlg:setup 以非交互方式重新进行身份验证

执行后检查

此技能完成后,在结束前检查:

  1. 命令是否成功?——如果没有,请修复导致失败的说明或错误表。
  2. 参数或输出是否有变化?——如果 tg-cli.ts 的接口发生变化,请更新 Usage 示例和 Parameters 表,使其保持一致。
  3. 是否需要变通方案?——如果你不得不临时变通(使用不同的标志、增加额外步骤),请更新此 SKILL.md,避免下次调用时还需要相同的变通方案。

仅在问题确实存在且可复现时更新,不要基于推测更新。

评论

支持 Markdown