@flink-app/slack-plugin

中文文档
2.0.0-alpha.134发布于 2026/11/07MITTypeScriptCommonJS近 30 天下载 2187

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

中文使用文档
文档目录45 节
  1. 特征
  2. 安装
  3. 设置
  4. 1. 配置编译器插件
  5. 2. 注册插件
  6. 3. 扩展您的应用程序上下文类型
  7. 4. 创建处理文件
  8. 处理器示例
  9. 响应@ mentions
  10. 处理模式
  11. 按模式匹配
  12. 按频道匹配
  13. 接通( 无路线)
  14. 路由属性
  15. 插件上下文
  16. send(opts)
  17. reply(message, text, opts?)
  18. getThread(message)
  19. getChannelHistory(opts)
  20. withConnection(id)
  21. addConnection(id, connection)
  22. removeConnection(id)
  23. listConnections()
  24. sendFile(opts)
  25. downloadFile(file)
  26. react(message, emoji)
  27. client
  28. 连接模式
  29. 套接字模式(建议开发)
  30. HTTP 模式
  31. 插件选项
  32. 多十年/ 动态连接
  33. 启动时多个连接
  34. 从数据库装入连接
  35. 运行时添加/ 重新移动连接
  36. 主动发送到特定连接
  37. 通过连接过滤路径
  38. 在处理器中访问连接信息
  39. 国 际
  40. Slack 应用程序设置
  41. 1. 瓶子范围
  42. 2. 活动订阅
  43. 3. 套接字模式(建议)
  44. 4. 安装到工作空间
  45. 多租户设置

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

双向黑消息插件 闪烁。使用自动发现的处理器文件接收并回复Slack消息——与 @flink-app/inbound-email-plugin。 。 。 .

特征

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

安装

pnpm add @flink-app/slack-plugin

设置

1. 配置编译器插件

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

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

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

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

2. 注册插件

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 整个应用程序.

// 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

// 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;

处理模式

// 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;

按模式匹配

// 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;

按频道匹配

// 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;

接通( 无路线)

// 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;

路由属性

财产类型说明
channelstring | RegExp | (msg) => boolean按频道标识匹配
patternstring | RegExp | (msg) => boolean匹配信件文本
isDMboolean只匹配直接消息
isMentionboolean仅匹配@mention
isThreadboolean只匹配线索回复
connectionIdstring | string[]只匹配来自特定连接的信件

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

插件上下文

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

send(opts)

向任何频道发送消息 .

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?)

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

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

getThread(message)

在线索中获取所有信件 .

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

getChannelHistory(opts)

从频道获取最近的消息 .

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

withConnection(id)

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

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

addConnection(id, connection)

运行时添加新连接 .

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

removeConnection(id)

停止并删除连接 .

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

listConnections()

列出活动连接ID.

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

sendFile(opts)

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

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 令牌进行认证.

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

react(message, emoji)

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

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

client

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

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

连接模式

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

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

HTTP 模式

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

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

插件选项

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

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

多十年/ 动态连接

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

启动时多个连接

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!,
    },
  },
});

从数据库装入连接

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,
      }])
    );
  },
});

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

// 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 处理器, 或访问插件上下文的任何地方 :

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

通过连接过滤路径

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

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 字段识别接收到的连接 :

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
};

国 际

从命令行发送测试消息 :

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

或使用环境变量:

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

Slack 应用程序设置

创建 Slack 应用程序 api.slack.com/应用程序 并配置以下内容。 见 偷懒 Bolt 正在获取指南 详细通过.

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 (英语)

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

见 黑袜子模式文件 详细情况.

4. 安装到工作空间

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

多租户设置

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

版本与发布记录

@flink-app/slack-plugin 共发布 75 个版本,首次发布于 2026/03/03;过去 12 个月发布了 75 个版本。

版本发布日期距今
2.0.0-alpha.134latest2026/11/078 天前
2.0.0-alpha.1332026/11/069 天前
2.0.0-alpha.1322026/11/0510 天前
2.0.0-alpha.1312026/10/2818 天前
2.0.0-alpha.1302026/10/2521 天前
2.0.0-alpha.1292026/10/2521 天前

关于 @flink-app/slack-plugin 的常见问题

@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 和提交记录判断。