mdadm chuck
If you haven't been living isolated in an igloo with no internet connection during the last year, I am sure you already heard about Slack, the famous real time messaging app for teams. We already talked about it and we even wrote a guide about how to code a complete Slack clone!
如果您去年没有在没有互联网连接的冰屋里过着孤立的生活,那么我相信您已经听说过Slack ,这是著名的团队实时消息传递应用程序。 我们已经讨论过了,甚至编写了有关如何编写完整的Slack克隆的指南 !
Slack has been built to be easy and fun to use and it offers a broad set of APIs that allows developers to extend its capabilities to make it even more useful and funny. One of the features I love from Slack is the Slackbot, a friendly robot available in every Slack team to guide users to create their profiles and to explain them how Slack works. But what I love even more is the possibility to build your own custom bots, special automated users that can respond to specific events and do useful things to help your team.
Slack的构建易于使用且有趣,它提供了广泛的API集,使开发人员可以扩展其功能,使其变得更加有用和有趣。 我喜欢Slack的功能之一是Slackbot ,这是每个Slack团队中都可以使用的友好机器人,它可以指导用户创建个人资料并向他们解释Slack的工作方式。 但是我更喜欢的是构建自己的自定义漫游器的可能性,这些特殊的自动化用户可以响应特定事件并做有用的事情来帮助您的团队。
In this article, we are going to build a custom Slack bot using NodeJs, and we want it to be a funny exercise that should put us in a good mood. For this sake we are going to build the mighty "NorrisBot", a bot that basically kicks asses, or, to put it another way, it brings a bit of Chuck Norris into your Slack team!
在本文中,我们将使用NodeJ构建一个自定义的Slack机器人,我们希望它是一个有趣的练习,应该使我们心情愉快。 为此,我们将构建强大的“ NorrisBot ”,该机器人基本上可以踢屁股,或者换句话说,它会给您的Slack团队带来一些Chuck Norris!
Our NorrisBot will be loaded with guns and jokes about Chuck Norris and it will tell a random one every time that someone says "Chuck Norris" in the chatroom.
我们的NorrisBot将载有关于Chuck Norris的枪支和笑话,每次有人在聊天室说“ Chuck Norris”时,它都会随机告诉一个人。
Get ready, it will be a funny ride!
准备好,这将是一个有趣的旅程!
松弛的实时API (Slack real time APIs)
To create a custom Slack bot or an even more complex application that reacts to what happens in your Slack organization you can use the Slack Real Time messaging API, a websocket-based API that allows you to receive events in real time and send messages to channels, private groups and users. This API is really well constructed and the documentation is clear, but instead of using the websocket directly we can use a very nice NodeJs module that makes things a lot easier, the slackbots module written by Mikhail Mokrushin. With this library we will just need to write some straightforward Javascript code. But before moving to our text editor we need to configure our channel extensions and create a new bot. This way we will obtain the API token that is required to authenticate our bot.
要创建对Slack组织中发生的事情做出React的自定义Slack机器人或什至更复杂的应用程序,可以使用Slack实时消息传递API (基于Websocket的API) ,该API允许您实时接收事件并将消息发送到渠道,私人团体和用户。 这个API是非常好构建和文档是明确的,但不是使用直接的WebSocket我们可以用一个非常漂亮的模块的NodeJS,使事情更容易,在slackbots由模块米哈伊尔Mokrushin写的。 使用该库,我们只需要编写一些简单的Javascript代码即可。 但是在转到文本编辑器之前,我们需要配置频道扩展并创建一个新的机器人。 这样,我们将获得验证我们的机器人所需的API令牌。
在您的Slack组织上创建一个新的Bot (Create a new Bot on your Slack organization)
To add a new Bot in your Slack organization you must visit the following url: https://yourorganization.slack.com/services/new/bot, where yourorganization must be substituted with the name of your organization (e.g. https://scotchio.slack.com/services/new/bot). Ensure you are logged to your Slack organization in your browser and you have the admin rights to add a new bot.
要在您的Slack组织中添加新的Bot,您必须访问以下网址:https:// yourorganization .slack.com / services / new / bot,其中yourorganization必须用您的组织名称替换(例如https:// scotchio .slack.com / services / new / bot)。 确保您已在浏览器中登录到Slack组织,并且您具有添加新漫游器的管理员权限。
In the first step you need to choose a name for your bot. Then you will move to another screen where you will be able to copy your API token:
第一步,您需要为机器人选择一个名称。 然后,您将转到另一个屏幕,可以在其中复制您的API令牌:
Copy the token in a safe place and save it, you will need it in a while. In this section you can also specify some more details about your bot, like the name and surname and also add an avatar image to make your bot look even more cooler. If you need an nice Chuck Norris face picture you can find it here.
将令牌复制到安全的地方并保存,一段时间后您将需要它。 在此部分中,您还可以指定有关您的机器人的更多详细信息,例如名称和姓氏,还可以添加头像图像,以使您的机器人看起来更酷。 如果您需要一张精美的查克·诺里斯(Chuck Norris)脸部图片,可以在这里找到。
设置项目 (Setting up the project)
Now that we have our API token we can start to setup our NodeJs project. I already created the NorrisBot Github repository with all the code that we are going to write. You can clone it if you would like to save you some keystrokes.
现在我们有了API令牌,我们可以开始设置NodeJs项目了。 我已经用我们要编写的所有代码创建了NorrisBot Github存储库 。 如果您想保存一些按键,可以克隆它。
For the sake of brevity I am assuming you already have NodeJs (at least version 0.10) and NPM installed in your machine.
为了简洁起见,我假设您已经在计算机中安装了NodeJ(至少是0.10版)和NPM。
First thing to do is to create our packages.json
file with the command
首先要做的是使用以下命令创建我们的packages.json
文件
npm init
Follow the guided configuration procedure specifying lib/norrisbot.js
under the entry point
option, we will create this file in a moment.
按照在entry point
选项下指定lib/norrisbot.js
的指导配置过程,我们将在稍后创建该文件。
Ok, now let's install our dependencies:
好的,现在让我们安装依赖项:
npm i --save slackbots@0.3.0 sqlite3
As we said before we will use the module slackbots
as abstraction layer to deal with the Slack API but we will also want to use an SQLite database as data source
如前所述,我们将使用模块slackbots
作为抽象层来处理Slack API,但我们还将希望使用SQLite数据库作为数据源
Note: Be sure to use version 0.3.0
of slackbots
as newer version are not perfectly compatible with what's illustrated in this tutorial.
注意:请确保使用slackbots
0.3.0
版本,因为较新的版本与本教程中所说明的并不完全兼容。
数据库 (The database)
Our SQLite database will allow us to store all the jokes and some configuration data. So we will have basically 2 tables inside it: the jokes
table and the info
table. The Internet Chuck Norris Database offers a very nice REST API that allows us to fetch a huge number of jokes about Chuck Norris, so I already preconfigured the database file by importing all the jokes from there. You can download the last version of the database from the GitHub repository. You will need to save it under the folder data/
inside your project folder. The script I used to generate the database is available in the GitHub repository as well. It's not a big deal and it's out of the scope of this article, but you can have a look at it if you want.
我们SQLite数据库将允许我们存储所有笑话和一些配置数据。 因此,我们基本上将在其中包含2个表: jokes
表和info
表。 Internet Chuck Norris数据库提供了一个非常好的REST API ,使我们能够获取有关Chuck Norris的大量笑话,因此我已经通过从那里导入所有笑话来预先配置了数据库文件。 您可以从GitHub存储库下载数据库的最新版本 。 您需要将其保存在项目文件夹内的data/
文件夹下。 我用来生成数据库的脚本也可以在GitHub存储库中找到。 没什么大不了的,不在本文的讨论范围之内,但是您可以根据需要进行查看 。
Slackbots软件包 (The Slackbots package)
Before starting to write our bot let's have a look at the main functions offered by the slackbots module.
在开始编写我们的机器人之前,让我们看一下slackbots模块提供的主要功能。
Let's have a look at a short example:
让我们看一个简短的例子:
var Bot = require('slackbots');
// create a bot
var settings = {
token: 'SOME TOKEN',
name: 'My Bot'
};
var bot = new Bot(settings);
bot.on('start', function() {
bot.postMessageToChannel('some-channel-name', 'Hello channel!');
bot.postMessageToUser('some-username', 'hello bro!');
bot.postMessageToGroup('some-private-group', 'hello group chat!');
});
As you can see from the code you have to require the SlackBot
constructor, from there you can instantiate a new bot object and attach callbacks to specific events. In the example we use the event start
that is triggered when the bot is successfully connected to the Slack server. Then we can use the methods offered by the library to post a message in a channel, to a user as private message or in a private group conversation.
从代码中可以看到,您需要SlackBot
构造函数,从那里可以实例化新的bot对象并将回调附加到特定事件。 在示例中,我们使用事件start
,该事件start
是在机器人成功连接到Slack服务器时触发的。 然后,我们可以使用库提供的方法在频道中以私人消息或私人群组对话的形式向用户发布消息。
实施机器人 (Implementing the bot)
Finally we can move to our favourite text editor and create the file lib/norrisbot.js
within our project folder. We will follow a slightly different approach compared to the previous example. Indeed instead of creating an instance of the Bot
class and listen for its events we will create a new class that inherits from the Bot
class. let's see how we can do this:
最后,我们可以转到我们喜欢的文本编辑器,并在我们的项目文件夹中创建文件lib/norrisbot.js
。 与前面的示例相比,我们将采用略有不同的方法。 实际上,我们将创建一个继承自Bot
类的新类,而不是创建Bot
类的实例并监听其事件。 让我们看看如何做到这一点:
扩展原始Bot类 (Extending the original Bot class)
# lib/norrisbot.js
'use strict';
var util = require('util');
var path = require('path');
var fs = require('fs');
var SQLite = require('sqlite3').verbose();
var Bot = require('slackbots');
var NorrisBot = function Constructor(settings) {
this.settings = settings;
this.settings.name = this.settings.name || 'norrisbot';
this.dbPath = settings.dbPath || path.resolve(process.cwd(), 'data', 'norrisbot.db');
this.user = null;
this.db = null;
};
// inherits methods and properties from the Bot constructor
util.inherits(NorrisBot, Bot);
module.exports = NorrisBot;
With the previous snippet of code we basically created the constructor function for our new Javascript class NorrisBot
. This class inherits all the methods of the Bot
class thanks to the util.inherits
function of NodeJs.
使用前面的代码片段,我们基本上为新的Javascript类NorrisBot
创建了构造函数。 由于util.inherits
函数,此类继承了Bot
类的所有方法。
In our constructor function we want to setup all the variables that our bot needs. The settings
object accepted as parameter is meant to be an extension of the original Bot
class, so we expect it to contain a token and a name. Furthermore we want to have the path where our SQLite database is stored (the dbPath
attribute) and we are defaulting the bot name to norrisbot.
在我们的构造函数中,我们要设置机器人需要的所有变量。 接受为参数的settings
对象是对原始Bot
类的扩展,因此我们希望它包含一个标记和一个名称。 此外,我们希望拥有存储SQLite数据库的路径( dbPath
属性),并且我们将机器人名称默认为norrisbot 。
We are also declaring the variables user
and db
that we are going to use later to store the current user information and the connection instance to the database.
我们还声明了变量user
和db
,我们将在以后使用它们来将当前用户信息和连接实例存储到数据库。
Run
功能 (The Run
function)
Now let's add a new function, the run
function:
现在让我们添加一个新功能,即run
功能:
NorrisBot.prototype.run = function () {
NorrisBot.super_.call(this, this.settings);
this.on('start', this._onStart);
this.on('message', this._onMessage);
};
This function is meant to allow us to instantiate our bot, but it will not connect to the Slack servers unless you explicitly call the run
method. This method calls the original constructor of the Bot
class and attaches two callback function respectively to the start
event and to the message
event. The latter event is fired when a real time message is received in the underline websocket connection managed by the Slackbots module.
此功能旨在允许我们实例化机器人,但是除非您显式调用run
方法,否则它将无法连接到Slack服务器。 此方法调用Bot
类的原始构造函数,并将两个回调函数分别附加到start
事件和message
事件。 当在由Slackbots模块管理的下划线websocket连接中接收到实时消息时,将触发后一个事件。
Ok so we need to write the _onStart
and _onMessage
functions which are the real core of our NorrisBot.
好的,所以我们需要编写_onStart
和_onMessage
函数,它们是_onMessage
的真正核心。
_onStart
函数 (The _onStart
function)
When our bot connects to the Slack server we want it to do the following 3 things:
当我们的机器人连接到Slack服务器时,我们希望它执行以下3件事:
- Load all the metadata related to the user representing the bot itself on the current Slack organization 将与代表机器人本身的用户有关的所有元数据加载到当前的Slack组织中
- Connect to the SQLite database 连接到SQLite数据库
- Check if it's the first time the bot is executed and if so send a greeting messages to alle the users 检查是否是第一次执行该漫游器,如果是,则向所有用户发送问候消息
NorrisBot.prototype._onStart = function () {
this._loadBotUser();
this._connectDb();
this._firstRunCheck();
};
As you can see we divided the 3 tasks in 3 separated functions. Let's see their code one by one.
如您所见,我们将3个任务划分为3个独立的函数。 让我们一一看一下他们的代码。
NorrisBot.prototype._loadBotUser = function () {
var self = this;
this.user = this.users.filter(function (user) {
return user.name === self.name;
})[0];
};
This function is very simple. When the original Bot
class connects to the Slack server it downloads a list with all the users in the organization and it saves it in the users
attribute as an array of objects. We just need to find the object that has the same username of our bot within that array.
这个功能很简单。 当原始Bot
类连接到Slack服务器时,它将下载组织中所有用户的列表,并将其作为对象数组保存在users
属性中。 我们只需要在该数组中找到与我们的机器人具有相同用户名的对象即可。
NorrisBot.prototype._connectDb = function () {
if (!fs.existsSync(this.dbPath)) {
console.error('Database path ' + '"' + this.dbPath + '" does not exists or it\'s not readable.');
process.exit(1);
}
this.db = new SQLite.Database(this.dbPath);
};
This one is really self-explanatory. We just check if the database file exists and then we create a new SQLite database instance.
这真的是不言自明的。 我们只是检查数据库文件是否存在,然后创建一个新SQLite数据库实例。
NorrisBot.prototype._firstRunCheck = function () {
var self = this;
self.db.get('SELECT val FROM info WHERE name = "lastrun" LIMIT 1', function (err, record) {
if (err) {
return console.error('DATABASE ERROR:', err);
}
var currentTime = (new Date()).toJSON();
// this is a first run
if (!record) {
self._welcomeMessage();
return self.db.run('INSERT INTO info(name, val) VALUES("lastrun", ?)', currentTime);
}
// updates with new last running time
self.db.run('UPDATE info SET val = ? WHERE name = "lastrun"', currentTime);
});
};
The _firstRunCheck
method is a little bit more complex than the previous two. We are using the info
table (defined as a key-value table) to see if the bot has been previously run. In fact we check if the record with name lastrun
already exists in the table, if it exists we just update the timestamp to the current one, otherwise we call the function _welcomeMessage
and create a new lastrun
record.
_firstRunCheck
方法比前两个复杂一些。 我们正在使用info
表(定义为键值表)来查看该漫游器是否先前已运行。 实际上,我们检查表中是否已经存在名称为lastrun
的记录,如果存在,则将时间戳更新为当前时间戳,否则调用函数_welcomeMessage
并创建新的lastrun
记录。
The welcome message function is super simple as you might expect:
如您所料,欢迎消息功能非常简单:
NorrisBot.prototype._welcomeMessage = function () {
this.postMessageToChannel(this.channels[0].name, 'Hi guys, roundhouse-kick anyone?' +
'\n I can tell jokes, but very honest ones. Just say `Chuck Norris` or `' + this.name + '` to invoke me!',
{as_user: true});
};
We are basically using the function postMessageToChanel
of the Bot
class. We select the first channel where the Bot is installed. An important detail to notice is the as_user
attribute passed in the configuration object. It allows the bot to post the message as itself (the message will be visualized with the avatar of the bot and it's name). You can also post messages with different avatars (also using emojis) or with different authors. Check out the Slack Real Time API documentation to understand how you can configure your messages.
我们基本上使用的是Bot
类的函数postMessageToChanel
。 我们选择安装Bot的第一个通道。 需要注意的重要细节是在配置对象中传递的as_user
属性。 它允许机器人将消息本身发布(消息将通过机器人的化身及其名称可视化)。 您还可以使用不同的头像(也使用表情符号)或不同的作者发布消息。 请查看Slack Real Time API文档,以了解如何配置消息。
_onMessage
函数 (The _onMessage
function)
Our _onMessage
function will intercept every real time API message that is readable by our bot, literally every chat message in the channels where the bot is installed, but also private messages directed to the bot or other real time notifications as notifications of user typing in a channel, edited or deleted messages, users joining or leaving the channel and so on.
我们的_onMessage
函数将拦截我们的机器人可以读取的每条实时API消息,实际上是该机器人安装渠道中的每条聊天消息,以及指向该机器人的私人消息或其他实时通知(例如,用户键入频道,已编辑或删除的消息,用户加入或退出频道等。
So keep in mind that in this case the naming can be a little bit confusing. Real time API messages are not just chat messages, but any kind of event that occurs within our Slack organization.
因此请记住,在这种情况下,命名可能会有些混乱。 实时API消息不仅是聊天消息,而且是我们Slack组织内发生的任何类型的事件。
We want our bot to filter all these events to detect public messages in channels that mentions "Chuck Norris" or the name of our bot, then we want to react to this message by replying with a random joke.
我们希望我们的机器人对所有这些事件进行过滤,以检测提及“ Chuck Norris”或我们的机器人名称的频道中的公开消息,然后我们希望通过随机开玩笑来对此消息做出React。
If we want to split all these checks in a list of operations this is exactly what we need to do:
如果我们想将所有这些检查拆分为一系列操作,这正是我们需要做的:
- Check if the event represents a chat message 检查事件是否代表聊天消息
- Check if the message has been sent to a channel 检查消息是否已发送到频道
- Check if the message come from a user that is different from the NorrisBot (to avoid loops) 检查消息是否来自与NorrisBot不同的用户(以避免循环)
- Check if the message mentions Chuck Norris 检查消息是否提到Chuck Norris
Let's see the code to do that:
让我们看看执行此操作的代码:
NorrisBot.prototype._onMessage = function (message) {
if (this._isChatMessage(message) &&
this._isChannelConversation(message) &&
!this._isFromNorrisBot(message) &&
this._isMentioningChuckNorris(message)
) {
this._replyWithRandomJoke(message);
}
};
The function receives a message object as parameter. The message contains all the informations that describes the real time event received through the Slack real time API. As you can see we have several helper functions that allows us to express the checking and processing logic in a more readable way.
该函数接收消息对象作为参数。 该消息包含描述通过Slack实时API接收到的实时事件的所有信息。 如您所见,我们有几个帮助程序功能,使我们能够以更易读的方式表达检查和处理逻辑。
Now let's discuss the helper functions one by one:
现在让我们一一讨论辅助函数:
NorrisBot.prototype._isChatMessage = function (message) {
return message.type === 'message' && Boolean(message.text);
};
The first helper function allows to check if a real time event corresponds to a message sent by a user (we basically checks if the message is of type "message" and if it contains some text).
第一个辅助功能允许检查实时事件是否与用户发送的消息相对应(我们基本上检查消息是否为“消息”类型,以及是否包含一些文本)。
NorrisBot.prototype._isChannelConversation = function (message) {
return typeof message.channel === 'string' &&
message.channel[0] === 'C';
};
The second check allows us to verify if the message is directed to a channel. Almost every real time message contains the attribute channel
that is an ID of the channel to which the event occurred. Again in this case the naming is a little bit misleading. The attribute channel
refers to any virtual communication channel that can be a "real" chat channel but also a private conversation between two users or a private group conversation. Every communication channel is identified by an alphanumeric ID, and to distinguish between these three cases we can have a look at the first character of the ID, when it starts with a "C" it represents a chat channel.
第二次检查使我们可以验证消息是否定向到某个频道。 几乎每个实时消息都包含属性channel
,该属性channel
是事件发生的通道的ID。 同样,在这种情况下,命名有点误导。 属性channel
是指任何虚拟通信通道,既可以是“真实”聊天通道,也可以是两个用户之间的私人对话,也可以是私人群组对话。 每个通信通道都由字母数字ID标识,为了区分这三种情况,我们可以看一下ID的第一个字符,当它以“ C”开头时,它代表一个聊天通道。
NorrisBot.prototype._isFromNorrisBot = function (message) {
return message.user === this.user.id;
};
The third check allows us to see if the message comes from a user who is not the NorrisBot itself. The NorrisBot very often writes messages that contains the string "Chuck Norris" and without this check we would end up with an infinite loop of infinite jokes. Yes, it might be fun at first but I guess anyone will get bored pretty soon!
第三次检查使我们可以查看消息是否来自不是NorrisBot本身的用户。 NorrisBot通常会编写包含字符串“ Chuck Norris”的消息,如果不进行此检查,我们最终将陷入无限笑话的无限循环。 是的,一开始可能很有趣,但我想任何人很快都会感到无聊!
NorrisBot.prototype._isMentioningChuckNorris = function (message) {
return message.text.toLowerCase().indexOf('chuck norris') > -1 ||
message.text.toLowerCase().indexOf(this.name) > -1;
};
The fourth check is used to see whether the text message mentions Chuck Norris or the name we chose for our NorrisBot.
第四个检查用于查看文本消息中是否提到Chuck Norris或我们为NorrisBot选择的名称。
If all these checks passes we call the function _replyWithRandomJoke
:
如果所有这些检查都通过,我们将调用_replyWithRandomJoke
函数:
NorrisBot.prototype._replyWithRandomJoke = function (originalMessage) {
var self = this;
self.db.get('SELECT id, joke FROM jokes ORDER BY used ASC, RANDOM() LIMIT 1', function (err, record) {
if (err) {
return console.error('DATABASE ERROR:', err);
}
var channel = self._getChannelById(originalMessage.channel);
self.postMessageToChannel(channel.name, record.joke, {as_user: true});
self.db.run('UPDATE jokes SET used = used + 1 WHERE id = ?', record.id);
});
};
This function extracts a joke at random from the database and posts it in the channel where the original message was written. Let's spend two minutes to see how the random pick is made and why. Our database jokes
table contains three columns: id
, joke
and used
. It's quite obvious from the code that the text of our joke is stored in the joke
field, but it's less obvious how the used
field works. Well, the used
field counts how many times a joke has been told. All the jokes are initialized with the used
count to zero, then the counter is incremented every time a joke has been told. This allow us to avoid to repeat the same joke in a short amount of time until all the other jokes has been told the same amount of time. Furthermore this trick makes the random pick a little bit faster than a generic ORDER BY RANDOM()
.
此函数从数据库中随机提取一个笑话,并将其发布到原始消息被写入的通道中。 让我们花两分钟的时间来看看如何进行随机选择以及原因。 我们的数据库jokes
表包含三列: id
, joke
和used
。 从代码中可以很明显地看到,我们的笑话文本存储在joke
字段中,但是used
字段的工作原理却不太明显。 好吧, used
字段会计算一个笑话被告知的次数。 used
计数将所有笑话初始化为零,然后在每次笑话被告知时,计数器就会增加。 这使我们避免在短时间内重复相同的笑话,直到所有其他笑话都被告知相同的时间为止。 此外,此技巧使随机选择比通用ORDER BY RANDOM()
快一点。
Notice that we are using another helper function called _getChannelById
. Realtime messages reference channels with IDs, but all the functions to post messages uses the name of the channel as parameter, so we need to retrieve the name of the channel given its ID. Here's the code of this last helper function:
注意,我们正在使用另一个名为_getChannelById
帮助器函数。 实时消息使用ID来引用通道,但是所有发布消息的功能均使用通道名称作为参数,因此我们需要在给定其ID的情况下检索通道名称。 这是最后一个辅助函数的代码:
NorrisBot.prototype._getChannelById = function (channelId) {
return this.channels.filter(function (item) {
return item.id === channelId;
})[0];
};
And so our NorrisBot
class is ready!
这样我们的NorrisBot
类就准备好了!
运行机器人 (Running the bot)
Now that our class is ready we need to create a launcher script to create an instance and run it. Let's create a new file called bin/bot.js
with the following content:
现在我们的类已经准备就绪,我们需要创建启动器脚本来创建实例并运行它。 让我们创建一个名为bin/bot.js
的新文件,其内容如下:
# bin/bot.js
'use strict';
var NorrisBot = require('../lib/norrisbot');
var token = process.env.BOT_API_KEY;
var dbPath = process.env.BOT_DB_PATH;
var name = process.env.BOT_NAME;
var norrisbot = new NorrisBot({
token: token,
dbPath: dbPath,
name: name
});
norrisbot.run();
The code is clean and simple: we just import our NorrisBot
class, we instantiate it and we launch the bot with the run
method. It's worth noticing that we are using some environment variables to make our bot configurable:
代码简洁明了:我们只需导入NorrisBot
类,实例化它,然后使用run
方法启动机器人。 值得注意的是,我们正在使用一些环境变量来使我们的机器人可配置:
BOT_API_KEY
: this variable is mandatory and must be used to specify the API token needed by the bot to connect to your Slack organizationBOT_API_KEY
:此变量是必需变量,必须用于指定机器人连接到Slack组织所需的API令牌BOT_DB_PATH
: optional variable that allows you to use a different database or to move the default one to a different pathBOT_DB_PATH
:可选变量,允许您使用其他数据库或将默认数据库移动到其他路径BOT_NAME
: the name of your bot, it's optional and it will default tonorrisbot
BOT_NAME
:您的机器人名称,它是可选的,默认为norrisbot
测试我们的机器人 (Testing our bot)
Ok, now we have everything we need to launch and test our bot. To start our bot we can run the launcher script with node bin/bot.js
but we also need to provide the API key with the env variable.
好的,现在我们拥有启动和测试我们的机器人所需的一切。 要启动我们的机器人,我们可以使用node bin/bot.js
运行启动脚本,但是我们还需要向API密钥提供env变量。
On Linux and Mac OSX you can simply run:
在Linux和Mac OSX上,您可以简单地运行:
BOT_API_KEY=your_api_key node bin/bot.js
On Windows you should get it working with:
在Windows上,您应该使用它:
set BOT_API_KEY=your_api_key & node bin/bot.js
If everything went fine you will see your NorrisBot appear in your Slack channel and a greeting message will be posted there. Try to invoke him by name several times and enjoy his jokes!
如果一切顺利,您会看到NorrisBot出现在您的Slack频道中,并在其中发布问候语。 尝试多次用名字来称呼他,并享受他的笑话!
Ok, now shut down the node process with ctrl+c
in your console, you will see your NorrisBot immediately disconnected from the channel.
好的,现在在控制台中使用ctrl+c
关闭节点进程,您将看到NorrisBot立即从通道断开连接。
I guess you don't want to keep the bot process running in your machine all the time so we need to deploy it into a real server to make it always available in your organization.
我想您不想让bot进程一直在您的机器上运行,因此我们需要将其部署到真实的服务器中以使其始终在您的组织中可用。
在Heroku上部署NorrisBot (Deploy the NorrisBot on Heroku)
A great place where to deploy our NorrisBot is Heroku. We can go reasonably well with their free worker tier and the deploy process is easy and convenient. Let's see how we can do that.
Heroku是部署NorrisBot的理想之地。 我们可以合理地使用他们的免费工作人员层,并且部署过程既简单又方便。 让我们看看我们如何做到这一点。
I am assuming you already have and account on Heroku and that you have installed git and the Heroku toolbelt on your machine.
我假设您已经在Heroku上拥有帐户并已在计算机上安装了git和Heroku工具带 。
First thing to do is to create a new Heroku app. Select a unique name for your app and a region and click on the "Create App" button.
首先要做的是创建一个新的Heroku应用程序 。 为您的应用和区域选择唯一的名称,然后单击“创建应用”按钮。
Then you need to go on your app settings tab and configure your environment variables.
然后,您需要进入“应用程序设置”标签并配置环境变量。
As you can see in the picture you need to specify the BOT_API_KEY
variable with your Slack API key and, if you want you can also specify the BOT_NAME
variable and, in case you moved your database somewhere different from the standard location, the BOT_DB_PATH
variable.
从图片中可以看到,您需要使用Slack API密钥指定BOT_API_KEY
变量,并且如果需要还可以指定BOT_NAME
变量,并且如果将数据库移动到与标准位置不同的位置,则需要BOT_DB_PATH
变量。
Now we need to define how Heroku will launch our application. To do so we need to create a file called Procfile
in the root of our project. This file must contain the following code:
现在我们需要定义Heroku如何启动我们的应用程序。 为此,我们需要在项目的根目录中创建一个名为Procfile
的文件。 该文件必须包含以下代码:
worker: node bin/bot.js
worker: node bin/bot.js
This way we are telling Heroku to create a worker dyno for our application by running our launcher script.
这样,我们告诉Heroku通过运行启动程序脚本为我们的应用程序创建辅助动态对象。
Once you are done with creating and configurig your Heroku app we need to deploy the code on the server. Heroku deployment is based on git so we need to create a new local git repository in our project folder. To do so just move to your project folder on the command line and run:
完成创建和配置Heroku应用程序后,我们需要在服务器上部署代码。 Heroku部署基于git,因此我们需要在项目文件夹中创建一个新的本地git存储库。 为此,只需在命令行上移至项目文件夹并运行:
git init
It will initialize a new repository. Now we need to add the project files to the repository and make the first commit, but before doing this we need to make sure the node_modules
folder is not accidentally committed to the repository as Heroky will take care to use Npm to download and keep our dependecies updated. The simplest way to do this is to create a .gitignore
file and write node_modules/
inside it. On Linux and Mac OSX you can do this by just running:
它将初始化一个新的存储库。 现在,我们需要将项目文件添加到存储库中并进行第一次提交,但是在执行此操作之前,我们需要确保不会将node_modules
文件夹意外提交到存储库中,因为Heroky将注意使用Npm下载并保留我们的依赖项。更新。 最简单的方法是创建一个.gitignore
文件,并在其中写入node_modules/
。 在Linux和Mac OSX上,您可以通过运行以下命令来执行此操作:
echo "node_modules/" >> .gitignore
Now don't forget to add all your files to the local repository and make your first commit with:
现在,不要忘记将所有文件添加到本地存储库并使用以下命令进行第一次提交:
git add --all
git commit -am "first version"
The next step is to connect our local git repository to our Heroku application using the Heroku toolbelt. To do so we need to login with the heroku login
command and then to launch
下一步是使用Heroku工具栏将本地git存储库连接到Heroku应用程序。 为此,我们需要使用heroku login
命令heroku login
,然后启动
heroku git:remote -a
Where, of course,
must be change with the real name of your heroku application (norrisbot
in my case).
当然在哪里
必须使用heroku应用程序的真实名称更改(在我的情况下为norrisbot
)。
This was the last step to configure your Heroku app and the deployment process using git. From now on you can deploy your app (or new version of it) by just pushing your git code to the Heroku remote with the following git command:
这是使用git配置Heroku应用程序和部署过程的最后一步。 从现在开始,您只需使用以下git命令将git代码推送到Heroku远程服务器即可部署您的应用程序(或应用程序的新版本):
git push heroku master
This command will take care of deploying the app on the server, downloading the new dependencies with Npm and finally to run your app on the server.
此命令将负责在服务器上部署应用程序,使用Npm下载新的依赖项以及最终在服务器上运行应用程序。
At this stage your NorrisBot will be available on your Slack channel and all your organization will be able to enjoy is company!
在这个阶段,您的NorrisBot将在您的Slack频道上可用,您的组织将可以享受的只有公司!
If you want to update your bot you just need to commit the new code in the local repository and push it to the Heroku remote.
如果要更新您的机器人,则只需在本地存储库中提交新代码,然后将其推送到Heroku远程服务器即可。
结论 (Conclusion)
I really hope you enjoyied this article and that from now on you will spend a bit of your time to write your own Slack bots.
我真的希望您喜欢这篇文章,从现在开始,您将花费一些时间来编写自己的Slack机器人。
If you want some ideas on how to improve the NorrisBot you can add new features as statistics, or a periodic chart with the top NorrisBot callers, the most appreciated jokes (by analyzing the reactions) and so on. Just break your imagination free and enjoy some coding for the sake of it.
如果您想了解有关如何改进NorrisBot的一些想法,可以添加新功能作为统计数据,或者添加具有最大NorrisBot调用者,最受赞赏的笑话(通过分析React)等的定期图表。 放开您的想象力,并享受一些编码。
If you want to develop more useful bots I can give you some other ideas:
如果您想开发更有用的机器人,我可以给您一些其他想法:
- The WatchdogBot, a bot that notifies when your website goes donw WatchdogBot ,一种通知您的网站何时下载的机器人
- The CashierBot, a bot that notifies you channel about new orders on your e-commerce website CashierBot ,一种机器人,可在您的电子商务网站上通知您有关新订单的渠道
- The MusicSpyBot, a bot that monitor the last.fm profile of your team members and make charts with the most appreciated songs and groups within your organization. MusicSpyBot机器人,它可以监视团队成员的last.fm个人资料,并使用组织内最受欢迎的歌曲和组制作图表。
Again, the possibilities are endless, your imagination and your coding skills are the limit! :)
同样,可能性无穷无尽,您的想象力和编码能力是极限! :)
If you have some other brilliant idea about how to improve the NorrisBot or about new Slack bots drop a line in the comments, I will be really happy to discuss those ideas with you.
如果您对如何改进NorrisBot或新的Slack机器人有其他出色的想法,请在评论中添加一行,我将非常高兴与您讨论这些想法。
Oops! I almost forgot! Of course we deployed the NorrisBot in our Slack, go and check it out!
糟糕! 我差点忘了! 当然,我们在Slack中部署了NorrisBot,请检查一下!
Thanks for reading. See you in the next post!
谢谢阅读。 下篇再见!
翻译自: https://scotch.io/tutorials/building-a-slack-bot-with-node-js-and-chuck-norris-super-powers
mdadm chuck