2

所以我正在为 Slack 开发一个机器人,它每周都会提到一个随机用户。我到了机器人确实做到这一点的地步,但我不确定如何避免重复。正如您在下面的屏幕截图中看到的那样,显示了重复的名称:

重名

这是我的代码:

// Handle events related to the websocket connection to Slack
controller.on('rtm_open', function (bot) {
  console.log('** The RTM api just connected!');

  // Get all users
  bot.api.users.list({}, function(err, list){

    // If list and members exist
    if (list && list.members) {

      list.members = list.members.filter(function(member) {
        return (member.real_name != undefined && member.real_name != "" && member.real_name != null && member.real_name != "slackbot");
      });

      // console.log(list.members);
      var previousRandomNumber = -1;

      // Every X amount of milliseconds
      var interval = setInterval(function() {
        var members = list.members;

        // Generating random number from 0 to how many members exist (exclusive) in the member list
        var randomNumber = Math.floor(Math.random() * members.length);

        console.log('1) previous: ' + previousRandomNumber + '  randomNumber ' + randomNumber);
        if (previousRandomNumber == randomNumber) {
          randomNumber = Math.floor(Math.random() * members.length);
        }
        console.log('2) previous: ' + previousRandomNumber + '  randomNumber ' + randomNumber);

        previousRandomNumber = randomNumber;

        // Get random name
        var randomName = members[randomNumber].name;

        //console.log(randomName);

        // If random name is null or undefined, reshuffle.
        if (randomName == null || randomName == "" || randomName == undefined) {
          console.log('user has been deleted');

          // clearInterval(interval);

        } else {
          console.log('actual person - ' + randomName);
          // Configuring webhook and sending message to channel
          bot.configureIncomingWebhook({url: 'https://hooks.slack.com/services/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'});
          bot.sendWebhook({
            text: '@' + randomName + ", you've been selected for #snapshot! ",
            channel: '#test',
          },function(err,res) {
            // handle error
          });
        }
      }, 3000); // 604800000 ms = 1 week
      console.log("message");
    }
  })
});

链接到 GitHub 上的 repo

有谁知道我如何以某种方式拼接数组中已经提到的名称?

4

2 回答 2

4

为避免重复,您需要存储已提及的用户 ID,并在每次运行时将其从用户列表副本中删除(例如每周一次)。在提到所有用户之前,您必须重置。

您可以通过多种方式存储 ID。例如,您可以将它们放入数据库中,或者您可以将它们保存到存储在服务器上的 JSON 文件中。

于 2017-04-13T22:46:49.407 回答
3

首先,我同意Erik的观点,即您需要明确确保您不会两次选择同一个成员。这可以通过将您已经选择(或仍需要选择)的成员存储在数据库中来完成。我们没有足够的详细信息来帮助您执行此操作。

然而,我想补充的是,选择随机成员而不重复的最佳方法不是随机选择用户并确保您之前没有选择该成员。这可能需要很长时间。您可以从数组中删除一个成员,但还有另一种方法。

洗牌(以正确的方式!)成员数组,然后按顺序简单地循环它们。选择所有成员后,您可以再次随机播放。这是一个使用 ES6 语法和生成器的示例,因为这似乎是它的理想用例。如果浏览器支持(没有IE,其他主流浏览器都可以)没有问题,你可以通过传入你的list.memberstouniqueRandomIterateiterator.next().value在你的interval中使用来使用它。

function shuffle(a) {
  for (let i = a.length; i; i--) {
    let j = Math.floor(Math.random() * i);
    [a[i - 1], a[j]] = [a[j], a[i - 1]];
  }
}

function* uniqueRandomIterate(array) {
  var ind = 0;
  while (true) {
    shuffle(array);
    for (let i = 0; i < members.length; ++i) {
      yield array[i];
    }
    console.log('got everyone, starting over');
  }
}

var members = ['a', 'b', 'c', 'd', 'e', 'f'],
    iterator = uniqueRandomIterate(members);
for (let i = 0; i < 3 * members.length; ++i) {
  console.log(iterator.next().value);
}
.as-console-wrapper {
  max-height: 100% !important;
}

于 2017-04-18T09:48:25.540 回答