You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何设置Slack机器人:实现命令触发问答及回答展示功能

搭建具备/aboutme/about功能的Slack机器人

我来一步步带你搞定这个Slack机器人,完全满足你的需求:用户发/aboutme时机器人会通过私密消息提问收集信息,发/about [用户名]时就能展示该用户的填写内容。我用Node.js的@slack/bolt框架来举例,这是Slack官方维护的框架,上手快,靠谱性拉满。

前期准备

  • 首先得有一个Slack工作区,登录Slack开发者后台创建一个新App,开启Bot用户权限,拿到两个关键信息:Bot Token(开头是xoxb-)和Signing Secret。另外记得开启Socket Mode,生成一个App Token(开头是xapp-),这个用来本地测试更方便,不用配置公网URL。
  • 电脑上装好Node.js和npm,确保开发环境没问题。

项目初始化与依赖安装

新建一个文件夹,打开终端执行下面的命令:

npm init -y
npm install @slack/bolt dotenv

然后创建一个.env文件,把刚才拿到的三个密钥填进去:

SLACK_BOT_TOKEN=xoxb-your-token-here
SLACK_SIGNING_SECRET=your-signing-secret-here
SLACK_APP_TOKEN=xapp-your-app-token-here

核心功能代码实现

新建index.js文件,咱们一步步写核心逻辑:

1. 初始化应用和存储配置

先把基础框架搭起来,用JSON文件临时存储用户信息(生产环境建议换数据库,比如PostgreSQL或者MongoDB):

const { App } = require('@slack/bolt');
require('dotenv').config();
const fs = require('fs').promises;
const path = require('path');

// 用来存用户信息的JSON文件路径
const USER_DATA_PATH = path.join(__dirname, 'userData.json');

// 初始化Slack应用
const app = new App({
  token: process.env.SLACK_BOT_TOKEN,
  signingSecret: process.env.SLACK_SIGNING_SECRET,
  socketMode: true,
  appToken: process.env.SLACK_APP_TOKEN,
});

2. 处理/aboutme私密提问功能

当用户发送/aboutme时,机器人会打开私密对话,依次发送问题并记录回答:

// 监听/aboutme命令
app.message(/^\/aboutme$/i, async ({ message, say, client }) => {
  try {
    // 打开和用户的私密对话
    const imResponse = await client.conversations.open({
      users: message.user,
    });
    const dmChannelId = imResponse.channel.id;

    // 发送初始提问消息
    await client.chat.postMessage({
      channel: dmChannelId,
      text: "我来收集你的信息啦~请依次回复以下问题:\n1. 你的真实姓名?\n2. 你的职位是?\n3. 你的兴趣爱好是?",
    });

    // 读取或初始化用户数据存储
    let userData = {};
    try {
      const data = await fs.readFile(USER_DATA_PATH, 'utf8');
      userData = JSON.parse(data);
    } catch (err) {
      // 文件不存在就初始化空对象
    }
    // 标记用户处于填写状态
    userData[message.user] = { status: 'pending', answers: {} };
    await fs.writeFile(USER_DATA_PATH, JSON.stringify(userData, null, 2));

    // 监听用户的私密回复,收集答案
    const collector = app.message({ channel: dmChannelId }, async ({ message: dmMessage, ack }) => {
      await ack();
      if (!userData[message.user]) return;

      const answerCount = Object.keys(userData[message.user].answers).length;
      switch (answerCount) {
        case 0:
          userData[message.user].answers.name = dmMessage.text;
          await client.chat.postMessage({ channel: dmChannelId, text: "好的,姓名已记录!请回答第二个问题:你的职位是?" });
          break;
        case 1:
          userData[message.user].answers.position = dmMessage.text;
          await client.chat.postMessage({ channel: dmChannelId, text: "职位已记录!最后一个问题:你的兴趣爱好是?" });
          break;
        case 2:
          userData[message.user].answers.hobbies = dmMessage.text;
          userData[message.user].status = 'completed';
          await client.chat.postMessage({ channel: dmChannelId, text: "完美!你的信息已经全部记录完成啦~" });
          collector.stop(); // 收集完就停止监听
          break;
      }
      // 更新存储的用户数据
      await fs.writeFile(USER_DATA_PATH, JSON.stringify(userData, null, 2));
    });
  } catch (err) {
    console.error('处理/aboutme出错:', err);
    await say('抱歉,处理你的请求时出问题了,请稍后再试!');
  }
});

3. 处理/about [用户名]查询功能

当用户发送/about [用户名]时,机器人会从存储中读取该用户的信息并展示:

// 监听/about [用户名]命令
app.message(/^\/about (\w+)$/i, async ({ message, say, matches }) => {
  try {
    const targetUsername = matches[1];
    // 通过用户名查找用户ID(Slack用户名可能重复,这里简化处理,生产环境可以优化)
    const usersList = await app.client.users.list();
    const targetUser = usersList.members.find(member => member.name.toLowerCase() === targetUsername.toLowerCase());

    if (!targetUser) {
      await say(`抱歉,找不到用户「${targetUsername}」哦!`);
      return;
    }

    // 读取用户数据
    let userData = {};
    try {
      const data = await fs.readFile(USER_DATA_PATH, 'utf8');
      userData = JSON.parse(data);
    } catch (err) {
      await say(`用户「${targetUsername}」还没有填写过个人信息哦!`);
      return;
    }

    const targetUserData = userData[targetUser.id];
    if (!targetUserData || targetUserData.status !== 'completed') {
      await say(`用户「${targetUsername}」还没有填写过个人信息哦!`);
      return;
    }

    // 格式化展示信息
    const infoText = `
*${targetUsername}的个人信息*
- 真实姓名:${targetUserData.answers.name}
- 职位:${targetUserData.answers.position}
- 兴趣爱好:${targetUserData.answers.hobbies}
    `;
    await say(infoText);
  } catch (err) {
    console.error('处理/about出错:', err);
    await say('抱歉,处理你的请求时出问题了,请稍后再试!');
  }
});

4. 启动应用

最后加一段启动代码:

// 启动机器人
(async () => {
  await app.start(process.env.PORT || 3000);
  console.log('Slack机器人已上线!');
})();

测试与部署

  1. 本地测试:在终端执行node index.js,然后在Slack工作区把Bot添加到频道,发送/aboutme看看是否收到私密消息,填写完信息后再发/about 你的用户名,检查信息是否正确展示。
  2. 部署到线上:可以用Heroku、Render这些平台,把代码推上去,配置好环境变量(就是.env里的三个密钥),确保机器人一直在线。

小提示

  • 存储用户信息用JSON文件只是临时方案,生产环境一定要换成数据库,避免并发读写的问题。
  • Slack的用户匹配逻辑可以优化,比如支持@提及用户(比如/about @James),这样更准确。
  • 记得在Slack后台的OAuth & Permissions里给Bot添加足够的权限:channels:historyim:historyusers:readchat:write这些,添加完后要重新安装Bot到工作区。

内容的提问来源于stack exchange,提问作者curious

火山引擎 最新活动