mcpField
U
using-mtcute

using-mtcute

github.com/mtcute开发58089 次安装5 天前更新
代码仓库

关于 using-mtcute

using-mtcute 是帮助 TypeScript 开发者使用 mtcute 的技能;mtcute 是面向 Telegram 原生 MTProto API 的类型安全库。它介绍平台包选择、客户端方法、更新处理,以及查询 API 类型和签名的内置工具。

主要功能

  1. 01选择适合目标平台的 mtcute 包
  2. 02配置 Telegram 客户端认证与生命周期
  3. 03使用高级方法操作 Telegram API
  4. 04通过 Dispatcher 路由更新
  5. 05查询方法、类和 TL 定义

适用场景

  1. 01构建 TypeScript Telegram 客户端
  2. 02实现消息与更新处理
  3. 03查找高级方法或原始 TL 调用签名

MCP 相关

README 提到可选用 Context7 MCP 查阅 mtcute 文档;未描述 MCP 服务或客户端实现。

安装

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

$npx skills add https://github.com/mtcute/mtcute --skill using-mtcute

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

包含的文件

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

tools/
get-class.js
get-constructor.js
get-method.js

详细介绍

mtcute — TypeScript MTProto 库

什么是 mtcute?

mtcute 是一个现代、类型安全的 TypeScript 库,用于 Telegram 的 MTProto 协议。与 Bot API 封装库(grammy、telegraf、node-telegram-bot-api)不同,mtcute 直接使用 Telegram 原生二进制协议,因此可以访问 完整的 Telegram API,而不仅仅是机器人 API 子集。

架构概览

核心包(你可能不会直接使用这些包):

  • @mtcute/core:MTProto 客户端、高级方法、TL 架构、类型
  • @mtcute/html-parser:HTML ↔ Telegram 实体
  • @mtcute/markdown-parser:Markdown ↔ Telegram 实体
  • @mtcute/file-id:Bot API file_id 解析

平台包(使用与你的目标平台相匹配的包):

  • @mtcute/node、@mtcute/bun、@mtcute/deno:服务端 JavaScript 的运行时绑定
  • @mtcute/web:浏览器绑定(IndexedDB、WebCrypto、WebSocket)

额外包(仅在需要其涵盖的特定功能时使用):

  • @mtcute/dispatcher:更新路由、过滤器、机器人框架
  • @mtcute/convert:从其他库导入会话
  • @mtcute/test:单元测试辅助工具

始终从平台包安装并导入所有内容,而不是从 @mtcute/core 导入:

// ✅ Correct — platform package pre-configures crypto, transport, storage
import { TelegramClient } from '@mtcute/node'

// ❌ Wrong — raw core client requires manual platform setup
import { TelegramClient } from '@mtcute/core'

基本用法

创建客户端
import { TelegramClient } from '@mtcute/node'

const tg = new TelegramClient({
  apiId: Number(process.env.API_ID),
  apiHash: process.env.API_HASH,
  storage: 'my-account', // SQLite file name (Node.js)
})
客户端生命周期

创建 TelegramClient 时,它会处于 disconnected 状态。

大多数情况下,你可以使用 start 方法来连接并验证身份:

// Bot login
const self = await tg.start({ botToken: process.env.BOT_TOKEN })

// User login (interactive)
const self = await tg.start({
  phone: () => input('Phone: '),
  code: () => input('Code: '),
  password: () => input('2FA password: '),
})

不过,在某些情况下,你可能需要手动控制生命周期:

// Manually connect
await tg.connect()

// Manually disconnect
await tg.disconnect()

// Disconnect and destroy the instance
await tg.destroy()
调用高级方法

TelegramClient 类提供了 300 多个高级便捷方法。下面列出了一些最常用的方法:

  • 消息:sendText、sendMedia、getHistory、editMessage、deleteMessages、forwardMessages、searchMessages,……
  • 聊天:getChat、getChatMember、banChatMember、setChatTitle、setChatPhoto,……
  • 用户:getUsers、getMe、setMyProfilePhoto,……
  • 文件:downloadFile、uploadFile、downloadAsStream,……
  • 对话:getDialogs、getPeerDialogs,……
  • 机器人:answerInlineQuery、answerCallbackQuery、setMyCommands,……
  • 论坛:createForumTopic、editForumTopic,……
  • 贴纸:getStickerSet、createStickerSet,……
  • 故事:sendStory、getStories,……
  • 身份验证:start、logOut、sendCode,……
  • 密码:enable2fa、change2fa,……
// Send a text message
await tg.sendText('me', 'Hello!')

// Send with formatting
await tg.sendText(chatId, html`Hello, <b>${name}</b>!`)

// Send media
await tg.sendMedia(chatId, {
  type: 'photo',
  file: 'file:./photo.jpg', // note the file: prefix!
  caption: 'Check this out',
})

// Get chat info
const chat = await tg.getChat('username')

// Download file
await tg.downloadToFile('path/to/save.jpg', photo)

有些方法还有对应的“批量”版本,接受数组而不是单个参数:

const durov = await tg.getUser('durov')
const [durov, telegram] = await tg.getUsers(['durov', 'telegram'])

// Similarly with `getChat` and `getChats`, `getPeer` and `getPeers`

不要混淆这两类方法。如果方法名是复数,它很可能会返回和/或接受数组,请牢记这一点。

Peer 解析

mtcute 的高级方法接受 InputPeerLike 作为聊天/用户参数,它可以是:

  • 数字 ID:123456789
  • 用户名字符串:'username'
  • 表示当前用户的 'me' / 'self'
  • tl.TypeInputPeer 对象
  • 高级对象(User、Chat、Message 等)
使用 Dispatcher 处理更新
import { Dispatcher, filters } from '@mtcute/dispatcher'

const dp = Dispatcher.for(tg)

dp.onNewMessage(filters.chat('private'), async (msg) => {
  await msg.replyText('Hello!')
})

dp.onNewMessage(filters.command('start'), async (msg) => {
  await msg.replyText('Welcome!')
})

dp.onCallbackQuery(filters.dataPrefix('btn_'), async (query) => {
  await query.answer({ text: 'Clicked!' })
})

// Start receiving updates
await tg.startUpdatesLoop()
原始 TL 方法调用

对于高级 API 未封装的方法,请使用 .call():

const result = await tg.call({
  _: 'messages.getEmojiKeywords',
  langCode: 'en',
})
// result is fully typed based on the method's return type

TL 类型系统

mtcute 根据 Telegram 的 TL 架构生成 TypeScript 类型。所有类型都位于 tl 命名空间下:

import { tl } from '@mtcute/core'
TL 概念TypeScript 名称示例
对象 usertl.RawUser{ _: 'user', id: number, ... }
带命名空间的对象 messages.chatstl.messages.RawChats
方法 users.getUserstl.users.RawGetUsersRequest
联合类型tl.TypeUsertl.RawUser | tl.RawUserEmpty

每个 TL 对象都有一个 _ 判别字段,其值为构造函数名称(例如 _: 'user')。

提供了类型守卫:tl.isAnyPeer()、tl.isAnyMessage() 等。

完整的 TL 架构以 JSON 格式提供,路径为 @mtcute/node/tl/api-schema.json(或任意平台包)。格式如下:

{
  "l": 223, // layer number
  "e": [ // array of TL entries
    {
      "kind": "class" | "method",
      "name": "user",
      "id": 826896937, // constructor ID
      "type": "User", // return/union type
      "arguments": [{
        "name": "id",
        "type": "int53", // base type name (union or primitive)
        "typeModifiers"?: {
          "predicate"?: "flags.0", // conditional field, e.g. "flags.3"
          "isVector"?: true, // optional: when true, type is actually Vector<type>
        }
      }, ...],
      "comment": "..."
    },
    ...
  ],
  "u": { "User": "..." } // union comments
}

当设置了 typeModifiers.predicate(例如 "flags.3")时,该字段为可选字段,且仅当 flags 字段的第 3 位设为 1 时才会出现。isVector 为 true 时,实际类型为 Vector<type>。

查找类型和方法签名

三个内置工具会从 node_modules 中已安装的 @mtcute/* 包读取信息。它们都支持模糊匹配,并能自动纠正拼写错误。

何时使用哪个工具:

  • 需要原始 TL 类型/方法定义或其 TS 接口 → get-constructor
  • 需要高级客户端方法签名(参数、返回类型、JSDoc)→ get-method
  • 需要高级封装类/接口定义(Message、Chat 等)→ get-class
  • 需要了解原始 API 调用所需的 TL 参数 → get-constructor --with-references
  • 不确定该使用哪个方法/类 → get-method --search 或 get-class --search
get-constructor:查找 TL 架构

显示 TL 定义、TypeScript 类型、联合类型成员,以及返回类型。

node .claude/skills/using-mtcute/tools/get-constructor.js <name>
node .claude/skills/using-mtcute/tools/get-constructor.js --with-references <name>

接受以下任意格式的输入:

  • TL 名称:user、messages.sendMessage
  • TS 类型名称:RawUser、TypeInputUser、tl.messages.RawChats、messages.RawGetHistoryRequest

需要了解构造函数参数或返回类型引用的类型时,请使用 --with-references;该参数会将所有被引用的构造函数/联合类型追加到输出中。

get-method:查找高级客户端方法

显示 TelegramClient 中完整的 JSDoc 和方法签名。

node .claude/skills/using-mtcute/tools/get-method.js <method-name>
node .claude/skills/using-mtcute/tools/get-method.js --search <keyword>
node .claude/skills/using-mtcute/tools/get-method.js --list
  • 默认模式:精确/模糊匹配方法名称;无匹配时,依次回退到名称和描述中的子字符串匹配
  • --search:同时搜索方法名称和描述,并列出所有匹配项
  • --list:打印所有可用方法及其单行描述
get-class:查找高级类型/类

显示 highlevel/types/ 中包含所有成员的完整类/接口/类型定义。

node .claude/skills/using-mtcute/tools/get-class.js <name>
node .claude/skills/using-mtcute/tools/get-class.js --no-members <name>
node .claude/skills/using-mtcute/tools/get-class.js --search <keyword>
node .claude/skills/using-mtcute/tools/get-class.js --list
  • 默认模式:精确/模糊匹配导出名称,并显示包含所有成员的完整定义
  • --no-members:仅显示声明行和 JSDoc,不显示主体
  • --search:同时搜索名称和描述,并列出所有匹配项(例如 --search keyboard)
  • --list:打印所有可用导出项及其单行描述

高级类型

mtcute 会将原始 TL 对象封装为带有辅助方法的便捷类:

  • Message — 封装 tl.RawMessage,提供 .replyText()、.editText()、.delete()、.forward() 等方法
  • Chat — 封装频道/群组/用户聊天信息
  • User — 封装 tl.RawUser
  • Document、Photo、Video、Audio、Voice、Sticker — 媒体类型
  • InlineQuery、CallbackQuery、ChatJoinRequest — 更新类型

这些类型位于 node_modules/@mtcute/core/dist/highlevel/types/ 中。

文本格式化

mtcute 支持使用带标签的模板字面量进行格式化:

import { html, md } from '@mtcute/node'

await tg.sendText(chat, html`<b>Bold</b> and <i>italic</i>`)
await tg.sendText(chat, md`**Bold** and *italic*`)

插入变量时,html 和 md 标签会自动进行转义。

常见模式

错误处理
import { tl } from '@mtcute/node'

try {
  await tg.sendText(chatId, 'hello')
} catch (e) {
  if (tl.RpcError.is(e, 'FLOOD_WAIT_%d')) {
    console.log(`Rate limited, wait ${e.seconds}s`)
  }
}
发送媒体
import { InputMedia } from '@mtcute/node'

// Upload from path (note the file: prefix!)
await tg.sendMedia(chatId, InputMedia.document('file:/path/to/file.pdf', {
  fileName: 'report.pdf',
}))

// Upload from buffer/stream
await tg.sendMedia(chatId, InputMedia.photo(buffer))

// Upload from URL
await tg.sendMedia(chatId, InputMedia.photo('https://example.com/image.jpg'))
键盘
import { BotKeyboard } from '@mtcute/node'

// Inline keyboard
await tg.sendText(chatId, 'Pick one:', {
  replyMarkup: BotKeyboard.inline([
    [BotKeyboard.callback('Yes', 'btn_yes'), BotKeyboard.callback('No', 'btn_no')],
    [BotKeyboard.url('Docs', 'https://mtcute.dev')],
  ]),
})

// Reply keyboard
await tg.sendText(chatId, 'Choose:', {
  replyMarkup: BotKeyboard.reply([
    [BotKeyboard.text('Option A'), BotKeyboard.text('Option B')],
  ]),
})
分页/迭代

许多方法都有对应的 iter* 方法,返回 AsyncIterableIterator:

// Iterate over chat history
for await (const msg of tg.iterHistory(chatId, { chunkSize: 100 })) {
  console.log(msg.text)
}

// Iterate over search results
for await (const msg of tg.iterSearchMessages({ query: 'hello', chatId })) {
  console.log(msg.id)
}

// Non-iter methods return paginated results with a `.next` cursor
const page = await tg.getHistory(chatId, { limit: 50 })
const nextPage = await tg.getHistory(chatId, { limit: 50, offset: page.next })
客户端事件

客户端通过 Emitter 实例提供连接生命周期和错误事件。使用 .add() 订阅,使用 .remove() 取消订阅:

// Connection state: 'offline' | 'connecting' | 'updating' | 'connected'
// 'updating' means connected but catching up on missed updates
tg.onConnectionState.add((state) => {
  console.log('Connection:', state)
})

// Unhandled errors (if no listener, errors are logged to console)
tg.onError.add((err) => {
  console.error('Error:', err)
})

// Raw TL updates (before dispatcher processing)
tg.onRawUpdate.add((update) => { ... })
代理/自定义传输(Node.js)
import { TelegramClient } from '@mtcute/node'
import {
  HttpProxyTcpTransport,
  SocksProxyTcpTransport,
  MtProxyTcpTransport,
  proxyTransportFromUrl,
} from '@mtcute/node'

const tg = new TelegramClient({
  // or parse from URL (socks4/5, http, https, mtproto):
  transport: proxyTransportFromUrl('socks5://user:[email protected]:1080'),
})

延伸阅读

完整文档和便于大模型阅读的参考资料:https://mtcute.dev/llms.txt。 如果可以使用 Context7 MCP,请优先使用它,而不是手动获取文档。库 ID 为 /mtcute/mtcute。

评论

支持 Markdown