# @flink-app/slack-plugin 中文文档

规范地址：https://npmcn.com/package/%40flink-app/slack-plugin/

版本：2\.0\.0-alpha\.134
npm 元数据更新时间：2026-11-07T11:33:28.203Z
中文译文更新时间：2026-11-15T03:29:58.099Z
软件包许可：MIT

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

原始 npm 页面：https://www.npmjs.com/package/%40flink-app/slack-plugin
原文对照：https://npmcn.com/package/%40flink-app/slack-plugin/?lang=original

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

- 包体积（解压后）：111 kB，37 个文件
- 模块格式：CommonJS
- TypeScript 类型：包内自带
- 运行依赖：2 个
- peer 依赖：@flink-app/flink \>=2\.0\.0-alpha\.134
- 首次发布：2026-03-02T19:21:34.218Z
- 最新版本发布：2026-11-07T11:29:56.946Z
- 近 30 天下载量：2187（2026-10-15 至 2026-11-13，npm 官方下载统计）
- 已发布版本数：75（近 12 个月 75 个）

## 中文简介

自动发现的SlackHandler文件的双向Slack消息的Flink插件

## 安装

```sh
npm install @flink-app/slack-plugin
```

也可以使用：`pnpm add @flink-app/slack-plugin`、`yarn add @flink-app/slack-plugin`、`bun add @flink-app/slack-plugin`

## README

# @flink-app/slack-plugin (英语)

双向黑消息插件 [闪烁](https://github.com/FrostDigital/flink-framework)。使用自动发现的处理器文件接收并回复Slack消息——与 `@flink-app/inbound-email-plugin`。 。 。 .

## 特征

-   接收频道消息、 DMs 、 引用和线索回复
-   向频道和线索发送消息
-   上传和下载已输入的文件 `SlackFile` 元数据
-   添加情感反应
-   获取上下文线索和频道历史
-   自动发现 `SlackHandler` 文件通过 Flink 编译器插件
-   套接字模式( 不需要公共 URL) 和 HTTP 模式
-   防止无限循环的瓶装信件过滤
-   自动 `<@BOTID>` 提及剥离
-   `requestContext` 用户/许可证注射一体化

## 安装

```bash
pnpm add @flink-app/slack-plugin
```

## 设置

### 1\. 配置编译器插件

在你身边 `flink.config.js`数字 :

```js
const { compilerPlugin } = require("@flink-app/slack-plugin/compiler");

module.exports = {
  compilerPlugins: [compilerPlugin()],
};
```

这让 Flink 编译器扫描 `src/slack-handlers/` 用于处理文件.

### 2\. 注册插件

```ts
import { slackPlugin } from "@flink-app/slack-plugin";

const app = new FlinkApp<AppCtx>({
  plugins: [
    slackPlugin<AppCtx>({
      connection: {
        mode: "socket",
        token: process.env.SLACK_BOT_TOKEN!,
        appToken: process.env.SLACK_APP_TOKEN!,
        signingSecret: process.env.SLACK_SIGNING_SECRET!,
      },
      // Optional: resolve your app's user from a Slack user ID
      resolveUser: async (msg, ctx) => {
        return ctx.repos.userRepo.findOne({ slackUserId: msg.userId });
      },
    }),
  ],
});
```

### 3\. 扩展您的应用程序上下文类型

导入 `SlackPluginCtx` 并把它当作一般论点 `FlinkContext`。这让你完全安全 `ctx.plugins.slack` 整个应用程序.

```ts
// src/Ctx.ts
import { FlinkContext } from "@flink-app/flink";
import { SlackPluginCtx } from "@flink-app/slack-plugin";

export interface Ctx extends FlinkContext<SlackPluginCtx> {
  repos: {
    // your repos here
  };
}
```

`ctx.plugins.slack` 然后完全输入——发送信件、管理连接和访问原始 `WebClient`。 。 。 .

> **说明:** 导入 `SlackPluginCtx` (无) `SlackApi`当扩展您的 `Ctx`。 。 。 . `SlackApi` 是内置的 API 类型,并非用于此目的.

### 4\. 创建处理文件

在 `src/slack-handlers/`。每个文件导出默认的处理器函数和一个可选 `Route`。 。 。 .

## 处理器示例

### 响应@ mentions

```ts
// src/slack-handlers/HandleMention.ts
import { SlackHandler, SlackRouteProps } from "@flink-app/slack-plugin";

export const Route: SlackRouteProps = { isMention: true };

const handler: SlackHandler<AppCtx> = async ({ ctx, message, slack }) => {
  const thread = await slack.getThread(message);
  await slack.reply(message, `You said: "${message.text}". Thread has ${thread.messages.length} messages.`);
};
export default handler;
```

### 处理模式

```ts
// src/slack-handlers/HandleDM.ts
import { SlackHandler, SlackRouteProps } from "@flink-app/slack-plugin";

export const Route: SlackRouteProps = { isDM: true };

const handler: SlackHandler<AppCtx> = async ({ message, slack }) => {
  await slack.reply(message, `Got your DM: "${message.text}"`);
};
export default handler;
```

### 按模式匹配

```ts
// src/slack-handlers/HandleHelp.ts
import { SlackHandler, SlackRouteProps } from "@flink-app/slack-plugin";

export const Route: SlackRouteProps = { pattern: /^help$/i };

const handler: SlackHandler<AppCtx> = async ({ message, slack }) => {
  await slack.reply(message, "Here's what I can do…");
};
export default handler;
```

### 按频道匹配

```ts
// src/slack-handlers/HandleSupport.ts
import { SlackHandler, SlackRouteProps } from "@flink-app/slack-plugin";

export const Route: SlackRouteProps = { channel: "support" };

const handler: SlackHandler<AppCtx> = async ({ ctx, message, slack }) => {
  await slack.reply(message, "A support agent will be with you shortly.");
};
export default handler;
```

### 接通( 无路线)

```ts
// src/slack-handlers/Fallback.ts
import { SlackHandler } from "@flink-app/slack-plugin";

const handler: SlackHandler<AppCtx> = async ({ message, slack }) => {
  console.log(`Unrouted message from ${message.userId}: ${message.text}`);
};
export default handler;
```

## 路由属性

| 财产 | 类型 | 说明 |
| --- | --- | --- |
| `channel` | `string | RegExp | (msg) => boolean` | 按频道标识匹配 |
| `pattern` | `string | RegExp | (msg) => boolean` | 匹配信件文本 |
| `isDM` | `boolean` | 只匹配直接消息 |
| `isMention` | `boolean` | 仅匹配@mention |
| `isThread` | `boolean` | 只匹配线索回复 |
| `connectionId` | `string | string[]` | 只匹配来自特定连接的信件 |

空出或省略 `Route` 匹配所有信件( 全部抓取) .

## 插件上下文

插件会曝光 `ctx.plugins.slack` 采用这些方法:

### `send(opts)`

向任何频道发送消息 .

```ts
await ctx.plugins.slack.send({
  channel: "general",
  text: "Hello from Flink!",
  threadTs: "1234567890.123456", // optional: reply in thread
  blocks: [],                    // optional: Block Kit blocks
});
```

### `reply(message, text, opts?)`

回复一个信息。 如果信件已经包含在内, 则继续线程, 否则将启动新线程 .

```ts
await slack.reply(message, "Got it!");
```

### `getThread(message)`

在线索中获取所有信件 .

```ts
const thread = await slack.getThread(message);
// thread.messages: SlackThreadMessage[]
```

### `getChannelHistory(opts)`

从频道获取最近的消息 .

```ts
const history = await slack.getChannelHistory({
  channelId: message.channelId,
  limit: 10,
});
```

### `withConnection(id)`

将范围上下文绑定到特定连接上. 用于从工作或HTTP处理器中主动发送.

```ts
const acmeSlack = ctx.plugins.slack.withConnection("acme");
await acmeSlack.send({ channel: "general", text: "Hello!" });
```

### `addConnection(id, connection)`

运行时添加新连接 .

```ts
await ctx.plugins.slack.addConnection("acme", {
  mode: "socket",
  token: "xoxb-...",
  appToken: "xapp-...",
  signingSecret: "...",
});
```

### `removeConnection(id)`

停止并删除连接 .

```ts
await ctx.plugins.slack.removeConnection("acme");
```

### `listConnections()`

列出活动连接ID.

```ts
const ids = ctx.plugins.slack.listConnections(); // ["default", "acme"]
```

### `sendFile(opts)`

上传文件到频道或线索中.

```ts
await ctx.plugins.slack.sendFile({
  channel: message.channelId,
  file: Buffer.from("hello world"),
  filename: "hello.txt",
  title: "My File",              // optional
  initialComment: "Here you go", // optional: message alongside the file
  threadTs: message.threadTs,    // optional: upload into thread
});
```

### `downloadFile(file)`

下载附在信件上的文件 。 由于 Slack 文件 URL 是私有的,所以使用bot 令牌进行认证.

```ts
if (message.files?.length) {
  const content = await slack.downloadFile(message.files[0]);
  // content is a Buffer
}
```

### `react(message, emoji)`

在消息中加入一个emoji反应.

```ts
await slack.react(message, "thumbsup");
```

### `client`

原始内容 `@slack/web-api` `WebClient` 以援助者所不能负担的事物发誓, 返回默认连接的客户端 .

```ts
await ctx.plugins.slack.client.reactions.add({
  channel: message.channelId,
  timestamp: message.ts,
  name: "thumbsup",
});
```

## 连接模式

### 套接字模式(建议开发)

不需要公开 URL 。 使用WebSocket通过一个应用级符号.

```ts
connection: {
  mode: "socket",
  token: "xoxb-...",
  appToken: "xapp-...",
  signingSecret: "...",
}
```

### HTTP 模式

通过HTTP接收事件. 需要在您的 Slack 应用程序中配置一个可公开访问的 URL .

```ts
connection: {
  mode: "http",
  token: "xoxb-...",
  signingSecret: "...",
  port: 3100, // default
}
```

## 插件选项

| 选项 | 类型 | 默认 | 说明 |
| --- | --- | --- | --- |
| `connection` | `SlackConnectionOptions` | —— 说 | 单一连接( 存储于 `"default"`) (中文(简体) ). |
| `connections` | `Record<string, SlackConnectionOptions>` | —— 说 | 启动时多个命名连接 . |
| `loadConnections` | `(ctx) => Promise<Record<string, SlackConnectionOptions>>` | —— 说 | 在输入时动态地装入连接( 例如从数据库) . |
| `stripMention` | `boolean` | `true` | 删除 `<@BOTID>` 文本中的前缀. |
| `resolveUser` | `(msg, ctx) => Promise<any>` | —— 说 | 从 Slack 消息中解析应用程序用户 . |
| `resolvePermissions` | `(user, ctx) => Promise<string[]>` | —— 说 | 解析已解决的用户权限 . |
| `onUnhandled` | `(msg, ctx) => Promise<void>` | —— 说 | 没有处理器匹配时调用 . |

你用得着 `connection`, (中文(简体) ), `connections`, (中文(简体) ), `loadConnections`,或者任何组合。 所有这些都是可选的——你可以从零连接开始,并在运行时动态地添加.

## 多十年/ 动态连接

对于每个租户连接自己Slack工作空间的SaaS应用程序,插件支持多个并发连接. 手持者同样工作—— `slack` 参数自动被扩展到收到消息的连接.

### 启动时多个连接

```ts
slackPlugin<AppCtx>({
  connections: {
    acme: {
      mode: "socket",
      token: process.env.ACME_SLACK_TOKEN!,
      appToken: process.env.ACME_SLACK_APP_TOKEN!,
      signingSecret: process.env.ACME_SIGNING_SECRET!,
    },
    beta: {
      mode: "socket",
      token: process.env.BETA_SLACK_TOKEN!,
      appToken: process.env.BETA_SLACK_APP_TOKEN!,
      signingSecret: process.env.BETA_SIGNING_SECRET!,
    },
  },
});
```

### 从数据库装入连接

```ts
slackPlugin<AppCtx>({
  loadConnections: async (ctx) => {
    const tenants = await ctx.repos.tenantRepo.findAll({ slackEnabled: true });
    return Object.fromEntries(
      tenants.map(t => [t.id, {
        mode: "socket" as const,
        token: t.slackToken,
        appToken: t.slackAppToken,
        signingSecret: t.signingSecret,
      }])
    );
  },
});
```

### 运行时添加/ 重新移动连接

```ts
// Add a new tenant's Slack connection
await ctx.plugins.slack.addConnection("acme", {
  mode: "socket",
  token: "xoxb-...",
  appToken: "xapp-...",
  signingSecret: "...",
});

// Remove it
await ctx.plugins.slack.removeConnection("acme");

// List active connections
const ids = ctx.plugins.slack.listConnections(); // ["acme", "beta"]
```

### 主动发送到特定连接

从工作, HTTP 处理器, 或访问插件上下文的任何地方 :

```ts
await ctx.plugins.slack.withConnection("acme").send({
  channel: "general",
  text: "Hello from Flink!",
});
```

### 通过连接过滤路径

Handlers 可以声明他们收听的连接 :

```ts
export const Route: SlackRouteProps = {
  isMention: true,
  connectionId: "acme",              // only this connection
  // connectionId: ["acme", "beta"], // specific set
  // omit connectionId → listen on ALL connections (default)
};
```

### 在处理器中访问连接信息

每个 `SlackMessage` 包含a `connectionId` 字段识别接收到的连接 :

```ts
const handler: SlackHandler<AppCtx> = async ({ message, slack }) => {
  console.log(`Message from connection: ${message.connectionId}`);
  await slack.reply(message, "Got it!"); // uses the correct connection automatically
};
```

## 国 际

从命令行发送测试消息 :

```bash
flink-slack send --token xoxb-... --channel general "Hello from CLI"
```

或使用环境变量:

```bash
export SLACK_BOT_TOKEN=xoxb-...
flink-slack send --channel general "Hello from CLI"
```

## Slack 应用程序设置

创建 Slack 应用程序 [api.slack.com/应用程序](https://api.slack.com/apps) 并配置以下内容。 见 [偷懒 Bolt 正在获取指南](https://slack.dev/bolt-js/getting-started) 详细通过.

### 1\. 瓶子范围

下 **授权和权限 − 范围**,添加:

| 范围 | 目的 |
| --- | --- |
| `chat:write` | 发送信件 |
| `files:read` | 从信件下载文件 |
| `files:write` | 上传文件 |
| `reactions:write` | 添加情感反应 |
| `channels:history` | 读取频道消息 |
| `groups:history` | 读取私有频道消息 |
| `im:history` | 读取模式 |
| `mpim:history` | 读取组 |

### 2\. 活动订阅

下 **事件订阅 – 订阅机器人事件**,添加:

-   `message.channels` ——频道消息
-   `message.groups` ——私人频道消息
-   `message.im` ——模式
-   `app_mention` — @ mentions (英语)

### 3\. 套接字模式(建议)

下 **设置 ~ 套接字模式**,将它切入并生成一个 app 级 符号 `connections:write` 范围。 这给你 `xapp-...` 用于 `appToken` 配置场. 不需要公开的 URL .

见 [黑袜子模式文件](https://api.slack.com/apis/connections/socket) 详细情况.

### 4\. 安装到工作空间

下 **安装 App**,单击 **安装到工作区**复制 **Bot 用户 OAuth 托肯** (单位:千美元)`xoxb-...`)和 **签名保密** (从) **基本情况**) (中文(简体) ).

### 多租户设置

对于多租户应用软件,每个租户都会通过Slack应用程序安装到自己的工作空间 [OAuth v2 (英语)](https://api.slack.com/authentication/oauth-v2). OAuth 流量完成后,存储每个租户的 `token`, (中文(简体) ), `appToken`,以及 `signingSecret`,然后调用 `addConnection()` 开始接收消息。 见 [黑发应用指南](https://api.slack.com/start/distributing) {\\fn黑体\\fs22\\bord1\\shad0\\3aHBE\\4aH00\\fscx67\\fscy66\\2cHFFFFFF\\3cH808080}为OAuth的全流.

## 常见问题

### @flink-app/slack-plugin 是什么？

自动发现的SlackHandler文件的双向Slack消息的Flink插件

### 如何安装 @flink-app/slack-plugin？

在项目目录运行 npm install @flink-app/slack-plugin，或使用 pnpm add / yarn add / bun add。它还需要宿主项目提供 peer 依赖：@flink-app/flink（\>=2\.0\.0-alpha\.134）。npm 7 及以上与 pnpm 8 及以上默认会自动安装必需的 peer 依赖，Yarn 需要手动安装。它还提供命令行工具 flink-slack，可以用 npx flink-slack 直接运行。

### @flink-app/slack-plugin 支持 TypeScript 吗？

支持。包内自带 TypeScript 类型声明（package\.json 声明了 types 入口），安装后即可获得类型提示，无需再安装 @types 包。

### @flink-app/slack-plugin 支持 ESM 还是 CommonJS？

以 CommonJS 形式发布，可以直接 require\(\)；在 ES Module 项目中也可以用 import 引入（Node\.js 会把 module\.exports 作为默认导出）。

### @flink-app/slack-plugin 可以商用吗？

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

### @flink-app/slack-plugin 的下载量有多少？

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

### @flink-app/slack-plugin 还在维护吗？

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

