# @dnuzi/baileys 中文文档

规范地址：https://npmcn.com/package/%40dnuzi/baileys/

版本：0\.1\.2
npm 元数据更新时间：2026-10-26T13:32:55.037Z
中文译文更新时间：2026-11-12T13:34:12.151Z
软件包许可：MIT

本文由上游 README 翻译，可能存在偏差，请结合原文核对 API、命令与配置。版权与许可归原作者所有。

原始 npm 页面：https://www.npmjs.com/package/%40dnuzi/baileys
原文对照：https://npmcn.com/package/%40dnuzi/baileys/?lang=original
项目主页：https://www.npmjs.com/package/@dnuzi/baileys
源码仓库：https://github.com/dnuzi

## 关键信息（来自 npm 元数据）

- 包体积（解压后）：8.9 MB，103 个文件
- 模块格式：ES Module
- TypeScript 类型：未声明
- Node.js 要求：\>=18\.0\.0
- 运行依赖：1 个
- 首次发布：2026-04-10T04:20:37.399Z
- 最新版本发布：2026-10-26T13:32:53.999Z
- 近 30 天下载量：2796（2026-10-13 至 2026-11-11，npm 官方下载统计）
- 已发布版本数：13（近 12 个月 13 个）

## 中文简介

WhatsApp Web API 图书馆由 DanuZz 修改.

## 安装

```sh
npm install @dnuzi/baileys
```

也可以使用：`pnpm add @dnuzi/baileys`、`yarn add @dnuzi/baileys`、`bun add @dnuzi/baileys`

## README

![@dnuzi/baileys](https://raw.githubusercontent.com/dnuzi/mova-npm-media/771b2cfb40aa7aa905214c6ca8e400040bb43b0f/assets/banner.svg)  

# @dnuzi/baileys (英语)

**一个快速,轻量级的WhatsApp Web API for Node.js.**

[![npm](https://img.shields.io/npm/v/@dnuzi/baileys?style=flat-square&color=black&label=npm)](https://npmjs.com/package/@dnuzi/baileys) [![version](https://img.shields.io/badge/version-v0.1.2-black?style=flat-square)](https://npmjs.com/package/@dnuzi/baileys) [![downloads](https://img.shields.io/npm/dm/@dnuzi/baileys?style=flat-square&color=black)](https://npmjs.com/package/@dnuzi/baileys) [![node](https://img.shields.io/badge/node-%E2%89%A518-black?style=flat-square&logo=node.js)](https://nodejs.org/) [![license](https://img.shields.io/badge/license-MIT-black?style=flat-square)](https://opensource.org/licenses/MIT)

[安装](https://npmcn.com/package/%40dnuzi/baileys/#readme--install) • 妇女 [快速启动](https://npmcn.com/package/%40dnuzi/baileys/#readme--quick-start) • 妇女 [业绩](https://npmcn.com/package/%40dnuzi/baileys/#readme--performance-optimization--latency-tuning) • 妇女 [信件](https://npmcn.com/package/%40dnuzi/baileys/#readme--messages) • 妇女 [交互式](https://npmcn.com/package/%40dnuzi/baileys/#readme--interactive-messages) • 妇女 [AI 里奇](https://npmcn.com/package/%40dnuzi/baileys/#readme--ai-rich-messages) • 妇女 [电话](https://npmcn.com/package/%40dnuzi/baileys/#readme--calls) • 妇女 [贷项](https://npmcn.com/package/%40dnuzi/baileys/#readme--credits)

![](https://raw.githubusercontent.com/dnuzi/mova-npm-media/771b2cfb40aa7aa905214c6ca8e400040bb43b0f/assets/divider.svg)

## 重点

![Multi-session, LID / PN / Username, Voice and video calls, Zero dependencies](https://raw.githubusercontent.com/dnuzi/mova-npm-media/771b2cfb40aa7aa905214c6ca8e400040bb43b0f/assets/features.svg)

|  |  |
| --- | --- |
| 🆔 **身份** | LID、电话号码和用户名支持 |
| ⚡ **业绩** | 为许多会话同时所建, CPU 和内存使用率低 |
| 📦 **依赖关系** | 没有运行时间依赖, 没有建立本地或WebRTC |
| 📞 **电话** | 音频和视频通话、播放列表、多呼叫 |
| 🧩 **信件** | 按钮、木马、部件、民意测验、事件、付款、人工智能 |
| 🗄️ **会议** | 多文件、 单文件、 SQLite 或 MongoDB 认证存储 |

由 [@达努兹](https://danuzz.movanest.xyz/) 软件包: [npmjs.com/package/@dnuzi/baileys (英语)](https://npmjs.com/package/@dnuzi/baileys)

> **v0.1.2 更新**:优化了所有内部缓存的CPU和RAM消耗(适应性扫描间隔,有限制的缓存限制,缓存-第一信号店mutex绕行,以及适当的定时器清理). Full CommunityJS需要()不使用ERR REQUIRE ASYNC MODULE的支持.
> 
> **v.0.1.1 更新**:固定VoIP视频通话渲染接通电话. 通过将 H.264 NALUs (SPS, PPS, 以及零碎的IDR keyframes) 正确包装.

![](https://raw.githubusercontent.com/dnuzi/mova-npm-media/771b2cfb40aa7aa905214c6ca8e400040bb43b0f/assets/divider.svg)

## QQ 安装

要求数 **节点.js 18+** 财务报告和审定财务报表 **FFmpeg 组合键**。呼吁也需要 `ffprobe` 备查 `PATH`。 。 。 .

```bash
npm install @dnuzi/baileys
```

```json
{
  "dependencies": {
    "@dnuzi/baileys": "v0.1.1"
  }
}
```

![](https://raw.githubusercontent.com/dnuzi/mova-npm-media/771b2cfb40aa7aa905214c6ca8e400040bb43b0f/assets/divider.svg)

## QQ 快速启动

用 QR 或配对代码和答案链接的完整机器人 `!ping`。 。 。 .

```javascript
import makeWASocket, {
  useMultiFileAuthState,
  DisconnectReason,
  extractMessageContent
} from '@dnuzi/baileys'

const PHONE_NUMBER = '' // e.g. '948123456789' to use a pairing code
const PAIR_CODE = ''    // optional custom 8-character code

const start = async () => {
  const { state, saveCreds } = await useMultiFileAuthState('./session')

  const sock = makeWASocket({
    auth: state,
    printQRInTerminal: !PHONE_NUMBER,
    syncFullHistory: false
  })

  sock.ev.on('creds.update', saveCreds)

  let pairingRequested = false
  sock.ev.on('connection.update', async ({ connection, lastDisconnect, qr }) => {
    if (qr && PHONE_NUMBER && !pairingRequested) {
      pairingRequested = true
      try {
        console.log('Pairing code:', await sock.requestPairingCode(PHONE_NUMBER, PAIR_CODE || undefined))
      } catch (err) {
        console.error('Could not request a pairing code:', err.message)
      }
    }

    if (connection === 'open') console.log('Connected as', sock.user?.id)

    if (connection === 'close') {
      const code = lastDisconnect?.error?.output?.statusCode
      if (code === DisconnectReason.loggedOut) {
        return console.log('Logged out. Delete ./session and run again to link a new device.')
      }
      if (code === DisconnectReason.connectionReplaced) {
        return console.log('This session was opened somewhere else. Not reconnecting.')
      }
      console.log(`Connection closed (${code}), reconnecting...`)
      setTimeout(start, 1000)
    }
  })

  sock.ev.on('messages.upsert', async ({ messages, type }) => {
    if (type !== 'notify') return
    for (const m of messages) {
      if (m.key.fromMe || !m.message) continue
      const content = extractMessageContent(m.message)
      const text = content?.conversation || content?.extendedTextMessage?.text
      if (text === '!ping') {
        await sock.sendMessage(m.key.remoteJid, { text: 'pong' }, { quoted: m }).catch(console.error)
      }
    }
  })
}

start()
```

**如何链接**

| 方法 | 步骤 |
| --- | --- |
| QR 代码 | 离开 `PHONE_NUMBER` 空的,然后从 _链接设备 – 链接设备_ |
| 对等码 | 设定 `PHONE_NUMBER`选择 _与电话号码连接_,输入代码 |
| 自定义代码 | 设定 `PAIR_CODE` 改为任意 8 个字符( 空 = 随机) |

> 您的登录已存储于 `./session`保持它私密和远离git.

### QQ 套接字选项

| 选项 | 默认 | 它会做什么 |
| --- | --- | --- |
| `auth` | – 说吧 – | **要求.** 这个 `state` 从一个认证助手 |
| `performanceMode` | `'balanced'` | 性能预设 : `'balanced'` (安全默认), `'high'` (高压缓存和最低缓存),或 `'low-memory'` (记录和档案管理所限制的环境) |
| `dedupTTL` | `30000` (单位:百万美元) | 发送信件的复制窗口 |
| `dedupMax` | `2000` | 在减重缓冲中跟踪的最大信件 |
| `groupMetadataCacheTTL` | `300000` (单位:百万美元) | 模拟组元数据缓存 TTL |
| `browser` | `Browsers.macOS('Chrome')` | 设备名称 _链接设备_ (另见: `.ubuntu()`, (中文(简体) ), `.windows()`, (中文(简体) ), `.appropriate()`(中文(简体) ) |
| `printQRInTerminal` | `false` | 在终端中打印每个 QR (`qr` 总是在 `connection.update`(中文(简体) ) |
| `qrTimeout` | `60000`,则 `20000` | 每个QR 保持有效时间 |
| `syncFullHistory` | `true` | 设定 `false` 用于打火机 |
| `markOnlineOnConnect` | `true` | 设定 `false` 在您的电话中保留通知 |
| `connectTimeoutMs` | `20000` | 打开握手暂停 |
| `keepAliveIntervalMs` | `30000` | 平时间隔 |
| `defaultQueryTimeoutMs` | `60000` | 服务器请求超时 |
| `getMessage` | `undefined` | 用密钥返回存储的信息, 这样重试和投票可以解密 |
| `disableStickyRouting` | `false` | `true` 停止发送 `ED` 在 URL 和 URL 中 `sticky_routing` 饼干 |
| `waWebSocketUrl` | `wss://web.whatsapp.com/ws/chat` | 只自定义终点 |
| `logger` | 内置 | 任何皮诺式的日志 |

![](https://raw.githubusercontent.com/dnuzi/mova-npm-media/771b2cfb40aa7aa905214c6ca8e400040bb43b0f/assets/divider.svg)

## \* 性能优化和 Latency Tuning

`@dnuzi/baileys` 包括一个内部性能引擎,被设计为将bot响应延迟最小化并消除冗余的网络操作而无需突破任何现有的Bairis API.

### 性能模式

您可以在初始化套接字时选择一个性能模式 :

```javascript
const sock = makeWASocket({
  auth: state,
  performanceMode: 'high' // 'balanced' | 'high' | 'low-memory'
})
```

| 模式 | 目标 | 说明 |
| --- | --- | --- |
| `'balanced'` _(默认)_ | 将军 | 安全,后向相容的默认. 记忆组元数据缓存( 5分) , 消息分解( 30s 窗口) , 请求连接, 以及安全事件隔离 . |
| `'high'` | 超快反应波茨 | 最大吞吐量和最低耐用度。 扩展缓存(15分钟组缓存,60s dedup),主动请求会合,扩大信号缓存,零上行懒记录. |
| `'low-memory'` | VPS / 嵌入式( ≤512MB 内存) | 压缩缓存边框(100个组,500个消息,2分TTL),并带有积极的垃圾收集. |

### \* 核心优化结构

1.  **快速信件管道和复制**
    
    -   以高速、有边界的循环缓存检查来信的系统(`MessageDeduplicator`在昂贵的密码解密之前.
    -   重复的信息发送系统得到确认并立即投放(~116,000+msgs/sec吞吐量).
    -   如果解密失败(例如需要的密钥缺失/再发送),该条目会自动被遗忘,因此重试可以无缝进行.
2.  **智能请求**
    
    -   防止重复并行查询(例如50个来信请求在同一毫秒的组元数据).
    -   重新使用飞行中的承诺 **50个同时提出的请求触发1个网络查询**,将服务器回路减少至98%.
3.  **记忆组元数据 & LID 缓存**
    
    -   `sock.groupMetadata(jid)` 缓存结果在组变化(主题,描述,参与者,设置)上自动无效.
    -   初始同步时预先聚集缓存( P)`groupFetchAllParticipating`)所以你的机器人不延迟地回答命令.
    -   直接通过 `sock.groupMetadataCache`。 。 。 .
4.  **事件泄漏断层隔离**
    
    -   已注册的中断或崩溃的收听器功能 `sock.ev.on('messages.upsert', ...)` 安全隔离.
    -   一个插件/ 处理器出错将 **永远不要撞倒其他听众或中断WhatsApp连接管道**。 。 。 .
5.  **优化序列化和发送器密钥**
    
    -   内存发送者密钥记录缓存避免了JSON在快速分组聊天流量时的恒定序列化和文件/数据库重读.
6.  **零头懒人伐木**
    
    -   用途 `logger.isLevelEnabled(level)` 和懒惰的参数评价,因此调试信息在运行生产时从未格式化.

### 现实世界基准

在自己的机器上运行基准套件 :

```bash
npm run benchmark
```

标准硬件的结果(20+节点):

-   **信件编辑器 :** 115 000克/秒吞吐量
-   **请求Coalescer :** 50名同时调用人员 —— 1个网络操作(以27米为单位100%破损)
-   **孤立事件调度 :** 19 000多起事件/秒,100%断层隔离
-   **LRU-TTL 缓存 :** 165 000+ 行动/秒

### QQ 会话存储

所有帮助者返回 `{ state, saveCreds }`这样你就可以自由交换了.

```javascript
import {
  useMultiFileAuthState,
  useSingleFileAuthState,
  useSqliteAuthState,
  useMongoDBAuthState
} from '@dnuzi/baileys'

const multi  = await useMultiFileAuthState('./session')              // one file per key
const single = await useSingleFileAuthState('./session.json')        // one file, flushed in batches
const sqlite = await useSqliteAuthState({ dbPath: './session.db' })  // SQLite (file-based, zero setup)
const mongo  = await useMongoDBAuthState({ url: 'mongodb://localhost:27017' }) // MongoDB (cloud & Docker)
```

#### SQLite Auth 存储

在 SQLite 数据库文件中存储会话证书和信号加密密钥 。 内建的WAL(Write-Ahead Digging)模式确保安全并存交易与超低内存高通.

> \[TIP\] **不需要额外的依赖!** 贝利斯包括一个内置的轻量级纯JS SQLite引擎,或者你可以插入 [`better-sqlite3`](https://www.npmjs.com/package/better-sqlite3) 用于本地 C++ 性能.

**1.基本布局(建设用发动机)**

```javascript
import makeWASocket, { useSqliteAuthState } from '@dnuzi/baileys'

const { state, saveCreds } = await useSqliteAuthState({
  dbPath: './session.db'
})

const sock = makeWASocket({
  auth: state,
  printQRInTerminal: true
})

sock.ev.on('creds.update', saveCreds)
```

**2\. 与 `better-sqlite3` (可选本地驱动)**

```javascript
import Database from 'better-sqlite3'
import makeWASocket, { useSqliteAuthState } from '@dnuzi/baileys'

const db = new Database('./session.db')

const { state, saveCreds } = await useSqliteAuthState({
  database: db
})

const sock = makeWASocket({
  auth: state
})

sock.ev.on('creds.update', saveCreds)
```

**备选方案 `useSqliteAuthState`**

| 选项 | 类型 | 说明 |
| --- | --- | --- |
| `dbPath` | `string` | SQLite 数据库的文件路径( 例如 ). `'./session.db'`) (中文(简体) ). 使用内置纯 JS 数据库引擎 |
| `database` | `object` | 现有数据库实例(例如来自 `better-sqlite3` 或者说 `sqlite3`(中文(简体) ) |

#### MongoDB Auth 存储

直接将会话证书和加密密钥存储于MongoDB(本地或MongoDB Atlas). 理想的云部署(Railway, Render, Heroku, AWS, Docker), 本地文件为ephemer, 或者在一个数据库中管理多个账户.

> \[注\] 当通过 MongoDB URI 连接时 (`url` 编号 : `uri`),确保 `mongodb` 在您的工程中安装了软件包 :
> 
> ```bash
> npm install mongodb
> ```

**1\. 通过MongoDB URI连接**

```javascript
import makeWASocket, { useMongoDBAuthState } from '@dnuzi/baileys'

const { state, saveCreds } = await useMongoDBAuthState({
  url: 'mongodb+srv://user:password@cluster.mongodb.net/?retryWrites=true&w=majority',
  dbName: 'whatsapp_bot',     // optional (default: 'baileys')
  collectionName: 'sessions', // optional (default: 'auth_state')
  sessionId: 'bot-1'          // optional: isolate multiple accounts in one collection
})

const sock = makeWASocket({
  auth: state,
  printQRInTerminal: true
})

sock.ev.on('creds.update', saveCreds)
```

**2\. 使用现有的MongoDB收藏或客户端**

如果您的应用程序已经连接到MongoDB, 请直接通过收藏—— 不需要额外的驱动程序连接 :

```javascript
import { MongoClient } from 'mongodb'
import { useMongoDBAuthState } from '@dnuzi/baileys'

const client = new MongoClient('mongodb://localhost:27017')
await client.connect()

const collection = client.db('whatsapp_bot').collection('sessions')

// Pass collection directly (with optional sessionId as 2nd argument)
const { state, saveCreds } = await useMongoDBAuthState(collection, 'main-session')
```

**3\. 与Mongoose一起使用**

```javascript
import mongoose from 'mongoose'
import { useMongoDBAuthState } from '@dnuzi/baileys'

await mongoose.connect('mongodb://localhost:27017/whatsapp_bot')

const collection = mongoose.connection.collection('sessions')
const { state, saveCreds } = await useMongoDBAuthState(collection)
```

**备选方案 `useMongoDBAuthState`**

| 选项 | 类型 | 说明 |
| --- | --- | --- |
| `url` 编号 : `uri` | `string` | MongoDB 连接字符串( 例如). `mongodb://localhost:27017` 或Atlas URI) |
| `collection` | `Collection` | 现有的MongoDB收藏或Mongoose模型 |
| `db` 编号 : `database` | `Db` | 现有的MongoDB数据库实例`client.db(...)`(中文(简体) ) |
| `client` | `MongoClient` | 现有 `MongoClient` 实例 |
| `dbName` | `string` | 数据库名称( 默认 ): `'baileys'` 或来自连接字符串的 DB ) |
| `collectionName` | `string` | 收藏名称( 默认 ): `'auth_state'`(中文(简体) ) |
| `sessionId` | `string` | 共享收藏中指定空间证书和密钥的会话ID |
| `mongoOptions` | `object` | 连接选项直接传递到 `MongoClient` |

### \* 断开原因

`lastDisconnect.error.output.statusCode` 地图到 `DisconnectReason`数字 :

| 代码 | 原因 | 做到这一点 |
| --- | --- | --- |
| `401` | `loggedOut` | 删除会话并再次链接 |
| `440` | `connectionReplaced` | 执行 **没有** 重新连接 |
| `515` | `restartRequired` | 成对后正常, 重新连接 |
| `428` 编号 : `408` | `connectionClosed` 编号 : `connectionLost` 编号 : `timedOut` | 网络投放, 重新连接 |
| `500` | `badSession` | 重新连接 |

当服务器关闭套接字时, `lastDisconnect.error.data` 包含 `wsCode` 财务报告和审定财务报表 `wsReason`。 。 。 .

![](https://raw.githubusercontent.com/dnuzi/mova-npm-media/771b2cfb40aa7aa905214c6ca8e400040bb43b0f/assets/divider.svg)

## QQ 信件

### 文本、提及、反应、联系人

```javascript
await sock.sendMessage(jid, { text: 'Hello there!' })

await sock.sendMessage(jid, {
  text: 'Hi @948123456789',
  mentions: ['948123456789@s.whatsapp.net']
}, { quoted: m, ephemeralExpiration: 86400 })

await sock.sendMessage(jid, { react: { text: '👍', key: m.key } })

await sock.sendMessage(jid, {
  contacts: {
    contacts: [{
      displayName: 'DanuZz',
      vcard: 'BEGIN:VCARD\nVERSION:3.0\nFN:DanuZz\nTEL;type=CELL:+948123456789\nEND:VCARD'
    }]
  }
})
```

### 媒体

```javascript
await sock.sendMessage(jid, { image: { url: './photo.jpg' }, caption: 'Nice view' })
await sock.sendMessage(jid, { video: { url: './clip.mp4' }, caption: 'Clip', gifPlayback: false })
await sock.sendMessage(jid, { audio: { url: './voice.ogg' }, ptt: true })
await sock.sendMessage(jid, { document: { url: './file.pdf' }, mimetype: 'application/pdf', fileName: 'file.pdf' })
await sock.sendMessage(jid, { sticker: { url: './sticker.webp' } })
```

**包装和相册**

```javascript
await sock.sendMessage(jid, { image: { url: './photo.jpg' }, viewOnce: true })                       // view once
await sock.sendMessage(jid, { video: { url: './clip.mp4' }, ptv: true })                             // video note
await sock.sendMessage(jid, { image: { url: './surprise.jpg' }, caption: 'Peekaboo', spoiler: true }) // spoiler

await sock.sendMessage(jid, {
  album: [
    { image: { url: './1.jpg' } },
    { image: { url: './2.jpg' } },
    { video: { url: './clip.mp4' } }
  ]
})
```

### 贴纸和贴纸包

**单标签**

```javascript
await sock.sendMessage(jid, { sticker: { url: './sticker.webp' } })
```

#### QQ 贴纸包

> \[大 若为 `sharp` 或者说 `@napi-rs/image` 未安装,则 `cover` 财务报告和审定财务报表 `stickers` 必须是已使用 WebP 格式.

```javascript
await sock.sendMessage(jid, {
  cover: {
    url: './path/to/image.webp'
  },
  stickers: [
    {
      data: {
        url: './path/to/image.webp'
      }
    },
    {
      data: {
        url: './path/to/image.webp'
      }
    },
    {
      data: {
        url: './path/to/image.webp'
      }
    }
  ],
  name: '📦 My Sticker Pack',
  publisher: 'DanuZz',
  description: 'Optional pack description'
})
```

**贴纸包选项**

| 财产 | 类型 | 说明 |
| --- | --- | --- |
| `cover` | `{ url: string }` | `Buffer` | **要求.** 包托盘图标 / 封面图像 |
| `stickers` | `Array<{ data: { url } | Buffer, emojis?: string[] }>` | **要求.** 贴花名单(最多60个贴花) |
| `name` | `string` | 标签包的名称(例如:. `'📦 My Sticker Pack'`(中文(简体) ) |
| `publisher` | `string` | 作者/出版商名称(如. `'DanuZz'`(中文(简体) ) |
| `description` | `string` | 包的可选描述 |

### 地点事件( E)

```javascript
await sock.sendMessage(jid, {
  location: { degreesLatitude: -6.2088, degreesLongitude: 106.8456, name: 'Monas' }
})

await sock.sendMessage(jid, {
  event: {
    name: 'Team Sync',
    description: 'Discuss the Q1 roadmap',
    startDate: new Date(Date.now() + 3600_000)
  }
})
```

### 选票

```javascript
await sock.sendMessage(jid, {
  poll: { name: 'Favorite language?', values: ['JavaScript', 'Python', 'Rust'], selectableCount: 1 }
})

// Quiz polls: newsletters only, require correctAnswer
await sock.sendMessage(newsletterJid, {
  poll: { name: 'Capital of Japan?', values: ['Tokyo', 'Osaka'], pollType: 1, correctAnswer: 'Tokyo' }
})

// Final tally of a poll you created
await sock.sendMessage(jid, {
  pollResult: {
    name: 'Favorite language?',
    votes: [{ name: 'JavaScript', voteCount: 12 }, { name: 'Python', voteCount: 9 }]
  }
})
```

### 编辑、删除、发夹、保存

| 行动 | 代码 |
| --- | --- |
| 编辑 | `sock.sendMessage(jid, { text: 'Updated text', edit: m.key })` |
| 删除 | `sock.sendMessage(jid, { delete: m.key })` |
| 键/ 取消键 | `sock.sendMessage(jid, { pin: m.key, type: 1, time: 86400 })` (单位:千美元)`type: 0` 撤销) |
| 保留/ 删除 | `sock.sendMessage(jid, { keep: m.key, type: 1 })` (单位:千美元)`type: 0` 删除) |
| 失踪( 组) | `sock.sendMessage(groupJid, { disappearingMessagesInChat: 86400 })` (单位:千美元)`true` = 7天 = 7天 = 7天 = 7天 = 7天 = 7天 = 7天 = 7天 = 7天 = 7天 = 7天 = 7天, `false` = 关闭) |

### 最新情况

```javascript
// jid can be an array to choose who sees the status
await sock.sendMessage([contactJid1, contactJid2], { text: 'Status update text' })
```

![](https://raw.githubusercontent.com/dnuzi/mova-npm-media/771b2cfb40aa7aa905214c6ca8e400040bb43b0f/assets/divider.svg)

## QQ 交互式信件

### 原生流量按钮

```javascript
await sock.sendMessage(jid, {
  text: 'Choose one:',
  footer: 'DanuZz',
  nativeFlow: [
    { text: '👋🏻 Yes', id: 'yes_1' },
    { text: '📞 Call', call: '948123456789' },
    { text: '📋 Copy', copy: 'PROMO123' },
    { text: '🌐 Source', url: 'https://example.com' },
    {
      text: '📋 Select',
      sections: [{ title: '✨ Section 1', rows: [{ title: '🏷️ Coupon', id: 'coupon_code' }] }]
    }
  ]
})
```

带有媒体标题, 使用 `caption` 改为 `text` (与图像、视频、文档、位置、产品有关的工作):

```javascript
await sock.sendMessage(jid, {
  image: { url: './promo.jpg' },
  title: 'Flash Sale',
  caption: 'Up to 50% off today only',
  footer: 'DanuZz',
  nativeFlow: [
    { text: 'Shop Now', url: 'https://shop.example.com' },
    { text: 'Copy Code', copy: 'SALE50' }
  ]
})
```

### 木马

卡片头可以是一个图像,视频或产品.

```javascript
await sock.sendMessage(jid, {
  text: 'Check out our new arrivals:',
  footer: 'DanuZz',
  cards: [
    { image: { url: './item-a.jpg' }, title: 'Item A', caption: 'New in stock', nativeFlow: [{ text: 'View', id: 'view_a' }] },
    { video: { url: './item-b.mp4' }, title: 'Item B', caption: 'Limited edition', nativeFlow: [{ text: 'View', id: 'view_b' }] },
    {
      businessOwnerJid: '1234567890@s.whatsapp.net',
      product: { title: 'Wireless Mouse', productImage: { url: './mouse.png' } },
      title: 'Wireless Mouse',
      caption: '$19.99',
      nativeFlow: [{ text: 'Buy Now', id: 'buy_mouse' }]
    }
  ]
})
```

### 部件( A2UI)

组合按钮,或通过 `nativeFlow: []` 没有.

```javascript
await sock.sendMessage(jid, {
  text: 'Widget demo',
  footer: 'A2UI Showcase',
  nativeFlow: [{ text: '🌐 Source', url: 'https://example.com' }],
  widget: {
    align: 'center',
    fallback: 'Widget cannot be loaded on this device', // optional
    items: [
      { text: 'Welcome to the Widget Demo', variant: 'title' }, // title | body | caption
      { text: 'This is a longer description.', variant: 'body' },

      { icon: 'info' },
      { icon: 'warning', style: 'symbol' },
      { icon: 'favorite', native: true },

      { image: 'https://example.com/banner.jpg', variant: 'header', fit: 'cover', description: 'Promo banner' },
      { video: 'https://example.com/preview.mp4' },
      { audio: 'https://example.com/audio.mp3', description: 'Listen to this audio' },

      { divider: 'horizontal' }, // or 'vertical'
      { button: 'Open Website', url: 'https://example.com', variant: 'primary' },

      { input: 'name', label: 'Enter your name', value: '', variant: 'shortText' }, // or 'longText'
      { input: 'email', label: 'Email', validationRegexp: '^[^@]+@[^@]+\\.[^@]+$' },
      { checkbox: 'I agree to the terms & conditions', value: false },
      { choice: ['Red', 'Green', 'Blue'], label: 'Favorite color', variant: 'mutuallyExclusive', displayStyle: 'chips', filterable: true },
      { choice: [{ label: 'Option A', value: 'a' }, { label: 'Option B', value: 'b' }], label: 'Multi-select', variant: 'multipleSelection', value: ['a'] },
      { slider: 100, min: 0, value: 50, label: 'Volume' }, // slider = max value
      { datetime: true, label: 'Pick a date', enableDate: true, enableTime: false },

      { row: [{ text: 'Left' }, { text: 'Center' }, { text: 'Right' }], justify: 'space-between', align: 'center' },
      { column: [{ text: 'Row 1' }, { text: 'Row 2' }], justify: 'start', align: 'stretch' },
      { list: [{ text: '• First item' }, { text: '• Second item' }], direction: 'vertical' }
    ]
  }
})
```

### 遗留模板按钮

旧格式. 偏爱 `nativeFlow`。 。 。 .

```javascript
await sock.sendMessage(jid, {
  text: 'Choose one:',
  footer: 'DanuZz',
  templateButtons: [
    { text: 'Reply', id: 'r1' },
    { text: 'Visit', url: 'https://example.com' },
    { text: 'Call', call: '+948123456789' }
  ]
})
```

### 模拟答复

发送回复, 如用户点击按钮或列表行 .

```javascript
await sock.sendMessage(jid, { buttonReply: { id: 'yes_1', displayText: 'Yes' }, type: 'plain' })
await sock.sendMessage(jid, { listReply: { id: 'row1', title: 'Row 1', description: 'desc' } })
await sock.sendMessage(jid, { flowReply: { name: 'single_select', paramsJson: JSON.stringify({ id: 'row1' }) } })
```

![](https://raw.githubusercontent.com/dnuzi/mova-npm-media/771b2cfb40aa7aa905214c6ca8e400040bb43b0f/assets/divider.svg)

## AI 丰富的信件

用可连锁的建设者构建结构丰富的响应.

```javascript
await sock.aiRich()
  .setTitle('Ai Rich Message')
  .addText('[HyperLink](https://example.com)\nCitation [](https://example.com)')
  .addImage('https://example.com/image.png')
  .addCode('javascript', `console.log('Hello World')`)
  .addHtml(['<html>Hello world</html>', 'Tab 1'], ['<html>Hi twin</html>', 'Tab 2'])
  .addTable([
    ['Name', 'DanuZz'],
    ['Bio', 'Im developer'],
    ['Age', '67']
  ])
  .addSource([['https://example.com/favicon.ico', 'https://example.com', 'Source']])
  .addTip('Tip Text')
  .addSuggest(['Continue', 'Cancel'])
  .send(jid, { quoted: m })
```

```javascript
// Animated progress indicator
await sock.aiRich().addProcess('Loading...').send(jid)

// Shorthand without the builder
await sock.sendMessage(jid, {
  aiRich: { title: 'Assistant', text: 'Here is what I found:', table: [['Name', 'Score'], ['Alice', '90']] }
})
```

> **旁通下载** 两者默认都在运行 `send()` 财务报告和审定财务报表 `sendMessage(jid, { aiRich })`。在发送后,信件会自己编辑,所以客户端不首先下载。 过 `bypassDownload: false` 把它关掉。 如果编辑失败, 抛出的错误有 `error.relayedKey` 设置到已发送信件的密钥.

**构建方法参考**

| 方法 | 目的 |
| --- | --- |
| `setTitle(title)` | 信件上显示的免责标签 |
| `setFooter(footer)` | 跟踪元数据文本块 |
| `setContextInfo(obj)` | 将额外字段合并到 `contextInfo` |
| `addText(text, opts?)` | 标出文字. 摘录 `[text](url)` 链接, `[](url)` 引用, `[text|w|h](<url>)` 拉特克语Name |
| `addCode(language, code)` | 语法高亮代码块 |
| `addTable(rows, opts?)` | `[[header...], [row...], ...]` 字符串数组 |
| `addImage(image)` | `string | Buffer | array`网格 |
| `addVideo(video)` | `string | Buffer | { url, mimeType?, duration? } | array` |
| `addSource(sources)` | `[icon, url, text][]` 源牌 |
| `addProduct(data)` | 产品卡或旋转木马阵列 |
| `addPost(data)` | 社交贴卡,或旋转木马的阵列 |
| `addReels(data)` | 里尔卡或数组 |
| `addTip(text)` | 小提示线 |
| `addSuggest(suggestion, opts?)` | 后续建议药 |
| `addProcess(title)` | 进展状况指标 |
| `addHtml(...)` | 一个内置的 HTML 块,或 `[html, title]` 选项卡对 |
| `build(opts?)` | 不发送而构建原始内容 |
| `buildEdit(jid, key, message)` | 构建绕行下载所用的编辑有效载荷 |
| `send(jid, opts?)` | 发去. `opts.bypassDownload` (默认) `true`)发送后续编辑,其他选项到 `sendMessage` |

![](https://raw.githubusercontent.com/dnuzi/mova-npm-media/771b2cfb40aa7aa905214c6ca8e400040bb43b0f/assets/divider.svg)

## 商业和支付

```javascript
// Product message
await sock.sendMessage(jid, {
  businessOwnerJid: '1234567890@s.whatsapp.net',
  image: { url: './mouse.png' },
  product: {
    title: 'Wireless Mouse',
    description: 'Ergonomic, 2.4GHz',
    currencyCode: 'USD',
    priceAmount1000: 19990, // $19.99
    retailerId: 'sku-001'
  }
})

// Payments
await sock.sendMessage(jid, { requestPaymentFrom: recipientJid, text: 'Payment for order #123' })
await sock.sendMessage(jid, { paymentInviteServiceType: 1 })
await sock.sendMessage(jid, { orderText: 'Your order summary', thumbnail: fs.readFileSync('./order-thumb.jpg') })
await sock.sendMessage(jid, { document: { url: './invoice.pdf' }, mimetype: 'application/pdf', invoiceNote: 'Invoice #1024' })
```

### 额外

```javascript
// Sponsored ad card on any message
await sock.sendMessage(jid, {
  text: 'Check this deal!',
  externalAdReply: {
    title: 'Big Sale',
    body: '50% off',
    thumbnail: fs.readFileSync('./thumb.jpg'),
    mediaType: 1,
    url: 'https://example.com'
  }
})

// Phone number requests
await sock.sendMessage(jid, { requestPhoneNumber: true })
await sock.sendMessage(jid, { sharePhoneNumber: true })

// Group invite card
await sock.sendMessage(jid, {
  groupInvite: { jid: groupJid, inviteCode: code, inviteExpiration: Date.now() + 3600_000, subject: 'My Group', text: 'Join us!' }
})

// Disable forwarding
await sock.sendMessage(jid, { limitSharing: true })
```

![](https://raw.githubusercontent.com/dnuzi/mova-npm-media/771b2cfb40aa7aa905214c6ca8e400040bb43b0f/assets/divider.svg)

## 电话

电话需要 `ffmpeg` 财务报告和审定财务报表 `ffprobe` 内 `PATH`创建 **一个 `Voip` 每个套接字** 打开后 重新连接后,您可以得到一个新的套接字, 所以创建一个新的 `Voip`。 。 。 .

### 打电话

```javascript
import Voip from '@dnuzi/baileys/voip'

const voip = new Voip(sock, {
  ffprobePath: 'ffprobe',
  voipLogLevel: 'warn',   // trace | debug | info | warn | error
  tmpDir: './tmp',        // temp folder for downloads
  maxConcurrentCalls: 1
})

const call = await voip.call('948123456789', './song.mp3')
await call.hangup() // or call.end()

await voip.call('948123456789') // ring only, no media
```

### 媒体、视频和播放列表

```javascript
await voip.call(jid, './song.mp3')                    // local file
await voip.call(jid, 'https://example.com/song.mp3')  // URL, downloaded first
await voip.call(jid, { audio: './voice.ogg' })
await voip.call(jid, './clip.mp4', '720p')            // video call

await voip.call(
  jid,
  ['./intro.mp3', './clip.mp4', 'https://example.com/outro.mp3'],
  '480p',
  {
    loop: false,          // repeat the playlist
    autoEndCall: true,    // hang up when the playlist ends
    autoDowngrade: true   // drop to audio when the peer turns every camera off
  }
)
```

| 项目 | 支助 |
| --- | --- |
| 音频格式 | `mp3` `ogg` `opus` `wav` `m4a` `aac` `flac` `weba` |
| 视频格式 | `mp4` `mov` `webm` `mkv` `avi` `m4v` `3gp` |
| 下载限制 | 音频 20 MB, 视频 50 MB |
| 决议 | `'240p'` `'360p'` `'480p'` `'720p'` `'1080p'` 或者说 `{ width, height, frameRate }` (默认 480p, 肖像自动旋转) |
| `jid` | 一个数字或一个JID,非数字被剥去 |

### 待命控制

```javascript
await call.silent(true)       // silence audio (false = resume, no arg = toggle)
console.log(call.isSilenced)

call.mute(true)               // mic only
call.raiseHand(true)
call.react('👍')              // returns false if not connected yet
await call.shareScreen(true)  // needs video, 1:1 only
await call.shareScreen(false)

const result = await call.upgradeToVideo()
// 'accepted' | 'rejected' | 'rejected_by_timeout' | 'error' | 'timeout' | 'cancelled'
```

> `shareScreen` 只告诉对等端正在共享屏幕 。 照片就是你们给的 `voip.coordinator.feedLiveVideo()`。 。 。 .

### 调用事件

```javascript
call.on('ringing', () => {})
call.on('connected', () => {})
call.on('ended', reason => {})          // 'connection_closed' if the socket drops
call.on('error', err => {})

call.on('item', ({ index, kind, source }) => {})
call.on('playlist_looped', () => {})
call.on('playlist_ended', () => {})
call.on('downgraded', () => {})         // video dropped to audio
call.on('silent', state => {})

call.on('peer_mute', muted => {})
call.on('hand_raise', ({ jid, raised }) => {})
call.on('reaction', reaction => {})
call.on('screen_share', share => {})
call.on('peer_video', change => {})
call.on('inbound_audio', pcm => {})     // Float32Array, 16 kHz mono, 60 ms
call.on('inbound_video', frame => {})   // decoded H.264 frame
call.on('audio_finished', () => {})     // current audio item reached its end
```

### 来电

```javascript
await voip.listen() // register call handlers, safe to call twice

voip.on('call_incoming', async call => {
  console.log('incoming from', call.peerJid, call.callId)
  await voip.acceptCall(call.callId)
})

voip.on('call_inbound_audio', ({ call, pcm }) => {})
voip.on('call_ended', call => console.log('ended', call.callId))

await voip.rejectCall(callId)
await voip.hangup(callId)
```

可用 `voip` 事件: `call_incoming`, (中文(简体) ), `call_state`, (中文(简体) ), `call_ended`, (中文(简体) ), `call_peer_mute`, (中文(简体) ), `call_inbound_audio`, (中文(简体) ), `call_inbound_video`, (中文(简体) ), `call_hand_raise`, (中文(简体) ), `call_reaction`, (中文(简体) ), `call_screen_share`, (中文(简体) ), `call_peer_video_state`, (中文(简体) ), `call_outbound_audio_finished`, (中文(简体) ), `call_error`。 。 。 .

`voip.coordinator` 是原始发动机( e)`feedLiveAudio`, (中文(简体) ), `feedLiveVideo`, (中文(简体) ), `setExternalAudioMode`(中文(简体) ).

### 多声召唤

```javascript
const voip = new Voip(sock, { maxConcurrentCalls: 3 })

const a = await voip.call('948111111111', './song.mp3')
const b = await voip.call('948222222222', './song.mp3')

// Many numbers at once
const results = await voip.callMany(
  ['948111111111', '948222222222', '948333333333'],
  './song.mp3'
)

for (const { jid, call, error } of results) {
  if (error) { console.log(jid, 'failed:', error.message); continue }
  call.on('ended', reason => console.log(jid, 'ended:', reason))
  call.on('error', err => console.error(jid, err))
}

voip.calls                  // active calls
voip.calls[0].callId
voip.calls[0].target        // dialed number
await voip.hangup(callId)   // end one call
await voip.end()            // end all calls
await voip.end(true)        // only release the slots
```

-   `maxConcurrentCalls` 默认为 `1`。每个电话都有自己的中继器、编码器和音频.
-   来电数到极限.
-   翻过极限抛出 `Maximum concurrent calls reached`内 `callMany()` 返回为 `error` 为了那个号码,其余的仍然通过.
-   `callMany()` 接受的媒体和选项与 `call()` 并拨打重复号码一次.
-   安全超时发射 `error` 如果呼叫从未结束(从105s开始).

![](https://raw.githubusercontent.com/dnuzi/mova-npm-media/771b2cfb40aa7aa905214c6ca8e400040bb43b0f/assets/divider.svg)

## • 信贷

这个图书馆是建立在原始的 **[贝利](https://github.com/WhiskeySockets/Baileys)** 以 **[@ 威士忌袜子](https://github.com/WhiskeySockets)**。 。 。 .

感谢贝利夫妇的维护者和贡献者: [pur壳](https://github.com/purpshell) • 妇女 [jlucaso1 (英语)](https://github.com/jlucaso1) • 妇女 [抖动](https://github.com/adiwajshing)

协议缓冲定义来自 [`wa-proto`](https://github.com/wppconnect-team/wa-proto) 以 [WPP 连接](https://github.com/wppconnect-team)。 。 。 .

附加代码和修改 [达努兹](https://danuzz.movanest.xyz/)。 。 。 .

![](https://raw.githubusercontent.com/dnuzi/mova-npm-media/771b2cfb40aa7aa905214c6ca8e400040bb43b0f/assets/divider.svg)

## 许可证

麻省理工学院 [达努兹](https://danuzz.movanest.xyz/)。见 [自由主义](https://opensource.org/licenses/MIT)。 。 。 .

## 联系人

[莫瓦内斯特](https://www.movanest.xyz/) • 妇女 [@达努兹](https://danuzz.movanest.xyz/)

![](https://raw.githubusercontent.com/dnuzi/mova-npm-media/771b2cfb40aa7aa905214c6ca8e400040bb43b0f/assets/banner.svg)

由QQ为WhatsApp dev社区所建.

## 常见问题

### @dnuzi/baileys 是什么？

WhatsApp Web API 图书馆由 DanuZz 修改\.

### 如何安装 @dnuzi/baileys？

在项目目录运行 npm install @dnuzi/baileys，或使用 pnpm add / yarn add / bun add。

### @dnuzi/baileys 支持 TypeScript 吗？

该包的 package\.json 没有声明类型入口。需要类型提示时，可以在 npm 上查找社区维护的 @types/dnuzi\_\_baileys 是否存在。

### @dnuzi/baileys 支持 ESM 还是 CommonJS？

以 ES Module 形式发布，推荐使用 import 引入。在 CommonJS 项目中，Node\.js 20\.19\+ / 22\.12\+ 可以直接 require\(\) 不含顶层 await 的 ES Module，更早的版本需要改用动态 import\(\)。

### @dnuzi/baileys 需要什么版本的 Node\.js？

package\.json 的 engines 字段要求 Node\.js \>=18\.0\.0。版本不符时 npm 默认只给出警告，开启 engine-strict 后会拒绝安装。

### @dnuzi/baileys 可以商用吗？

@dnuzi/baileys 使用 MIT 许可。宽松许可：允许商业使用、修改和再分发，通常只需在分发时保留原版权与许可声明。以上为概括，不构成法律意见，请以许可原文为准。

### @dnuzi/baileys 的下载量有多少？

根据 npm 官方下载统计，@dnuzi/baileys 在 2026/10/13 – 2026/11/11 这 30 天内被下载 2,796 次，日均约 93 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入，适合横向比较热度，不能直接等同于使用人数。

### @dnuzi/baileys 还在维护吗？

最新版本 0\.1\.2 发布于 2026/10/26（18 天前）；至今共发布 13 个版本，其中过去 12 个月发布了 13 个；首次发布于 2026/04/10。发布频率只是参考信号：功能稳定的工具可能很少需要更新，建议结合源码仓库的 issue 和提交记录判断。

