electron 图标制作
聊天机器人越来越受欢迎。 Facebook正在致力于提供一个构建Messenger机器人的框架,该框架将允许企业所有者完全在Facebook的消息传递应用程序内部建立其客户支持。 订购披萨 ,安排您的下一次就诊时间,或者只是想为下一次旅行找到最便宜的航班? 在消息传递应用程序中查找机器人联系人,并像在好友列表中询问人类联系人一样,询问您需要什么。
Facebook消息产品副总裁David Marcus在11月的Web Summit上发表了有关Facebook参与聊天机器人的演讲,很明显,Facebook制定了大计划,使客户和企业所有者不仅可以将客户支持集成到Messenger聊天中,还可以将其集成到Messenger聊天中。还有一些您通常希望是网页或应用程序中的表单的交互(例如,订购食物,配置下一次购车等 )。
在本教程中,我们将使用Electron和Microsoft Bot Framework (MBF)创建用于日常Scrum会议的Skype机器人。
从技术角度看,当前最受欢迎的框架似乎是Microsoft Bot Framework,它使您可以将bot与基本上所有流行的聊天连接起来。
但是还有其他选择:
我们将创建用于创建Scrum团队和使用Electron添加成员的配置GUI,然后使用MBF创建一个机器人,该机器人将从配置中读取内容,并向所有添加的用户提示三个Scrum日常会议问题。 当每个人都提供了答案后,该漫游器会将会议摘要发送给团队中的所有参与者。
不,我们不是在制造橄榄球机器人。 对于那些不熟悉scrum的人,这里是TL; DR :
Scrum是一种方法,由针对敏捷开发过程(例如,软件开发团队)的预定义规则和最佳实践组成,特别是针对大约3至6人的团队(非常粗糙且变化很大)。 这些规则/最佳实践可以包括以下内容(再次,非常粗略,并且变化很大,因为每个团队都根据自己的需要对其进行了一些调整):
这些会议之一是每日Scrum会议。 通常每个团队成员都是在早上做第一件事,向每个团队的其他成员提供他们在前一天所做的工作以及所取得的进展的最新信息。 此外,每个团队成员都将透露他们今天计划做的事情,以及最后但并非最不重要的任何障碍,尤其是那些会阻碍任务进一步发展的障碍。
日常Scrum会议通常是“实时”进行的,但是对于具有不同时区和/或不同位置的远程团队而言,这可能会带来问题。 这就是我们制造的机器人进来的地方。
先决条件:
僵尸程序和配置程序的所有代码都可以在本文随附的存储库中找到 。
如果您不熟悉Electron,最好阅读一下这篇文章 (至少是介绍性的段落),该文章描述了Electron的基本知识及其Swift流行的原因。 即将出现的许多新的桌面应用程序都在使用Electron (例如Slack,Visual Studio Code)。
要设置样板代码,我们将使用Yeoman生成器 。
转到您要项目驻留的文件夹,然后运行以下命令
npm install -g yo generator-electron
这将在您的计算机上全局安装Electron软件包。 从这一点开始,您可以在任意位置调用电子发生器,这是我们的下一步:
yo electron
全面介绍PHP和MySQL,从而实现服务器端编程的飞跃。
原价$ 11.95 您的完全免费
这将为您提供运行“ Hello World” Electron应用程序所需的所有文件。 它将自动运行npm install
,因此,在Yeoman完成后,您可以运行:
npm start
并且您应该看到一个新的应用程序窗口弹出。
index.js
是应用程序的入口点。 我建议您打开此文件,然后自己看看是否发生了什么。
function createMainWindow() {
const win = new electron.BrowserWindow({
width: 600,
height: 400
});
win.loadURL(`file://${__dirname}/index.html`);
win.on('closed', onClosed);
return win;
}
createMainWindow()
将通过调用BrowserWindow类的构造函数来创建主窗口(显然是上尉),在这里您可以提供一些窗口选项,例如宽度,高度,背景色等等 。
此函数中要注意的重要事项是win.loadURL
方法。 为什么这很重要? 在这里,我们可以看到应用程序的内容实际上只是HTML文件而已! 没有魔术,也没有新功能或框架来学习制作桌面应用程序。 它所需要的只是Web开发人员的专业知识,因此也使我们所有Web开发人员都成为了桌面应用程序开发人员!
const app = electron.app;
app.on("window-all-closed", () => {
// ...
});
app.on('activate', () => {
// ...
});
app.on('ready', () => {
// ...
});
Electron为我们提供了事件的回调,请参见此处的完整列表。
ready –如果您熟悉jQuery,则ready
事件将类似于jQuery(document).ready()
。
启动 -启动发出的每个应用程序窗口投入集中时间。
windows-all- closed-在关闭应用程序的所有窗口时触发,这使得它可以进行任何清理。 请谨慎使用此代码,因为在某些情况下它不会被调用 (例如,如果您从代码中调用app.quit()
或用户按下Cmd + Q)。
入口点文件index.js
包含应用程序启动和退出的特定代码,并且更用于全局设置。 我们不在此放置应用程序逻辑。 正如我们已经看到的,应用程序本身就是一个HTML文件。 因此,让我们进入index.html
并为配置器GUI添加一些元素。
Electron boilerplate
Teams
用此代码替换当前HTML文件。 在正文的最后,我们添加了对app.js
脚本的引用,这是我们的应用逻辑所在。 请记住,Electron窗口不过是嵌入其中的浏览器窗口,因此在开发过程中,您可以使用标准快捷方式来重新运行代码(F5,Ctrl + R)并打开类似Chrome的开发人员工具(F12)。
在项目的根目录中添加一个新文件,将其命名为app.js
,然后从此处粘贴代码。 这里没有新的事情发生,只有好的旧JavaScript。
对于持久数据,我们将使用一个简单的JSON文件,足以满足我们的需求。 如果您想扩展应用程序,则必须用数据库解决方案代替。
有一个用于添加新团队的按钮,然后在每个团队内部我们可以添加成员。 每个成员在Skype上均以其用户名表示。 稍后,当我们开始制作机器人本身时,您会看到机器人模拟器内置了一个聊天客户端,用于测试。 该用户的用户名是user 。
此外,我们可以通过从下拉列表中选择团队名称来加载团队。 在每个团队的底部,都有一个输入框,表示我们应该进行每日Scrum会议的一天中的时间。 我们将此值保存为时间戳,代表从午夜到会议时间的秒数。
现在让我们启动配置器,并尝试添加一个团队和一个名为“ user”的用户。
现在,我们可以从下拉列表中选择添加的团队,并向其中添加一些用户。
重要说明:您必须使用用户名user添加用户,因为仿真器无法更改名称,而这就是硬编码的名称。 为了使机器人能够在测试时识别我们,它必须是user 。
将时间设置为00:00(或其他时间),然后点击保存 。
检查您的teams.json
文件,这应该是其内容:
{
"alpha": {
"members": {
"user": {},
"almir bijedic": {}
},
"time": 0
}
}
稍后将由机器人使用。
MBF SDK有两个版本:C#和Node.js。 我们将使用Node版本。 该机器人通过REST API工作 ,您可以手动调用它,也可以使用提供的开源SDK 。 在本教程中,我们将使用SDK,因为它要快得多。 如果您需要将漫游器与现有应用程序集成在一起,或者由于某种原因无法使用Node.js / C#,则使用自定义函数调用API 可能是一个更好的选择。
要在本地测试该机器人,有两种选择:
我们将使用第二个选项,即“更真实”。
构建聊天机器人的主要类称为UniversalBot
。 值得一提的是, UniversalCallBot
也存在,它可以让您进行呼叫,但是在本教程中我们不会对此进行介绍。 此外,聊天机器人的重点是允许用户无需调用即可进行交互,因为似乎我们更喜欢发短信而不是call 。
为了确定漫游器将如何回答来自用户的传入消息,我们使用路由。 这与常规的Web应用程序非常相似,例如:
// bot is an instance of UniversalBot
bot.dialog("/", function (session) {
session.send("Hello World");
});
请注意,这里的bot
是UniversalBot
类的实例。
每当用户向机器人发送任何消息时,这都会向用户发送“ Hello World”。
bot.dialog()
具有两个参数:路由,以及在该路由处于活动状态时执行的函数。 在瀑布模型对话框(瀑布将在下一节中说明)的情况下,第二个参数可以是一个函数数组 ,然后将依次执行另一个函数,从而与用户进行交互。
现在将是一个很好的尝试时间。 返回您的Electron项目,并在名为bot
内部添加一个新文件夹。 在该文件夹中运行npm init
并填写基本信息,您唯一需要输入的就是app.js
作为入口点, node app.js
作为开始脚本。 完成后,在bot
文件夹的根目录中创建一个新文件app.js
现在,我们需要为我们的机器人安装依赖项。
npm install --save botbuilder restify fs-extra
接下来,转到我们在bot
文件夹中创建的app.js
文件,并包含我们需要的库。
// app.js
var restify = require("restify"),
builder = require("botbuilder"),
fse = require("fs-extra");
我们需要创建一个Restify服务器,该服务器将侦听某个端口上的传入连接。
// app.js
// Setup Restify Server
var server = restify.createServer();
server.listen(process.env.port || process.env.PORT || 3978, function () {
console.log("%s listening to %s", server.name, server.url);
});
现在,我们将把Restify服务器连接到MBF bot REST服务。
// Create chat bot
var connector = new builder.ChatConnector({
appId: process.env.MICROSOFT_APP_ID,
appPassword: process.env.MICROSOFT_APP_PASSWORD
});
var bot = new builder.UniversalBot(connector);
server.post("/api/messages", connector.listen());
您可以对节点使用MICROSOFT_APP_ID
和MICROSOFT_APP_PASSWORD
环境变量来提供您的登录凭据。 这用于对Microsoft Bot目录进行身份验证。
注意: ChatConnector的替代方法是ConsoleConnector ,它将在正在运行的应用程序的控制台中要求输入。 这种方法不需要我们稍后要安装的模拟器
最后但并非最不重要的一点是,在根路由上添加一个简单的对话框,该对话框仅输出“ Hello World! 给用户。
bot.dialog("/", function(session) {
session.send("Hello World!");
});
让我们从ChatConnector
角度来看这一切是如何工作的,因为这可能会使我们在使用ChatConnector
所做的事情有些混乱,以及为什么我们需要重新调整服务器。
用户将您的漫游器添加为Skype联系人。
为了测试我们刚刚制作的这个简单的机器人,我们必须下载并安装模拟器,该模拟器既充当客户端Skype应用程序(用户),又充当Skype REST API服务器,这是上图的左侧。
转至仿真器页面并下载,安装和运行它。
现在,我们需要为模拟器提供运行我们的机器人代码的端点。
返回bot文件夹并运行npm start
。 您应该会看到以下内容:
restify listening to http://[::]:3978
您可以通过提供PORT
Node环境变量或通过在文件开头更改硬编码回退值3978来更改此端口。
这是本地主机上端口3978上的端点。因此,我们将其放入仿真器。 此外,别忘了我们在/ api / messages路由上进行监听。
将Microsoft应用ID和密码保留为空; 因为我们正在本地运行测试,所以不需要这样做。 单击连接 。
现在您可以尝试该机器人了。 您将始终收到Hello World消息,因为这是我们到目前为止已配置的全部。
我们将需要一个比这更聪明的机器人。 在下一部分中,我们将实现以下路线:
/
–仅当已经注册的用户在Scrum会议之间向机器人发送消息时,才使用根对话框路由。 我们添加它的唯一目的是向用户显示正在发生的事情,即使我们没有参加Scrum会议或注册,该机器人仍在侦听。 /firstRun
–我们需要以某种方式注册用户并保存其地址,以便以后能够向他们发送消息。 /dailyScrumDialog
–将有一个运行setInterval()
的计时器,该计时器将检查所有团队的每日站立会议的时间。 如果有一个小组的会议时间到了,请查找所有在该bot上注册的用户(通过注册,我们表示已经在配置器中添加到该团队中的用户,并且他们还将该bot作为Skype上的联系人添加了并且他们已经向漫游器发送了至少一条消息)。 /report
–这里最简单的对话框,仅用于将会议报告发送给团队的所有成员。 这将由运行setInterval()
的另一个函数触发,该函数检查团队中的每个成员是否都已完成回答这三个问题。 如果是,请将每个人的答案发送给每个团队成员。 瀑布是最基本的bot对话类型。 它确实像听起来的那样:它顺着流淌而没有回去。 我们将函数数组作为第二个参数传递给机器人的dialog
函数。 在上一步有提示的情况下,每个功能都会一个接一个地执行。
builder.Prompts.text(session, "Message to send")
是从用户请求输入的主要方式。 用户响应后,将执行数组中的下一个函数。 这次它具有两个参数:会话对象和包含用户消息的结果对象。
bot.dialog("/", [
function (session) {
builder.Prompts.text(session, "Hey there, how are you doing?");
},
function (session, results) {
console.log(results.response); // This will print out whatever the user sent as a message
session.send("Great! Thank you for letting me know.")
}
]);
用新对话框替换以前的根对话框,然后尝试一下。
请注意,我们还可以保存和保留用户数据。
bot.dialog("/", [
function (session) {
if (session.userData.howIsHe) {
session.send(session.userData.howIsHe);
} else {
builder.Prompts.text(session, "Hey there, how are you doing?");
}
},
function (session, results) {
session.userData.howIsHe = results.response;
session.send("Great! Thank you for letting me know.")
}
]);
运行此命令将保存用户的响应,然后在每条下一条消息上将响应发送给他们。
如前所述,该漫游器通过对话框来组织聊天。 与用户的对话开始后,机器人将默认对话框推入堆栈顶部。 然后,我们可以使用以下功能之一重新路由到其他对话框和/或结束它们。
此函数停止当前对话框,将具有指定路由的对话框添加到堆栈顶部,一旦完成新调用的对话框,它将返回到先前对话框中beginDialog()
位置。
当我们调用endDialog()
,当前对话框从堆栈中弹出,然后返回到堆栈上的下一个对话框。
与endDialog()
相同,不同之处在于我们可以传入一些变量以供调用对话框(堆栈中的下一个对话框)使用。
如果我们不希望一旦新一个完成返回到先前的对话框,我们可以使用replaceDialog()
代替beginDialog()
取消对话框将导致对话框从堆栈中弹出(取消),直到到达具有提供的ID的对话框为止,然后对话框也被取消,并将控制权返回给原始调用者。 然后,该调用者还可以检查results.resumed
变量以检测取消。
另外,除了返回原始调用方之外,还可以通过提供对话框的ID来替换它。
这是取消所有对话框的便捷方法。 基本上就像调用session.cancelDialog(0)
(0是堆栈中第一个对话框的ID,因此所有对话框将被取消)。 当您还想清除用户的会话数据时,这非常方便。
在用户启动与僵尸程序的对话之前,僵尸程序无法与Skype用户交谈(或与此有关的任何其他聊天平台-不要忘记MBF与多个聊天客户端配合使用)。 有道理不是吗? 主要是为了避免垃圾邮件。
为了能够启动对话框,我们需要用户的地址(包含用户ID和对话ID的对象),因此,我们需要某种先运行逻辑来存储用户的地址供以后使用。
MBF为我们提供了一个中间件,我们可以使用该中间件来指示我们要将用户定向到第一次启动对话框的路径。
var version = 1.0;
bot.use(builder.Middleware.firstRun({ version: version, dialogId: "*:/firstRun" }));
这会将用户首次注册引导到“ firstRun”路由,然后我们必须对其进行定义。
bot.dialog("/firstRun", [
function (session, args) {
if (session.userData.user && session.userData.team) {
session.userData["BotBuilder.Data.FirstRunVersion"] = version;
session.replaceDialog("/dailyScrum");
} else {
builder.Prompts.text(session, "Hello... What's your team name?");
}
},
function (session, results) {
// We'll save the users name and send them an initial greeting. All
// future messages from the user will be routed to the root dialog.
var teams = readTeamsFromFile();
var providedTeamName = results.response.toLowerCase();
var user = session.message.user.name.toLowerCase();
if (teams[providedTeamName] && Object.keys(teams[providedTeamName].members).indexOf(user) > -1) {
teams[providedTeamName].members[user].address = session.message.address;
writeTeamsToFile(teams);
session.userData.user = user;
session.userData.team = providedTeamName;
session.send("Hi %s, you are now registered for the %s team daily scrum. We will contact you at the time of the meeting, which is at %s", user, providedTeamName, timeToString(teams[providedTeamName].time));
} else {
session.send("Wrong team! Try again :D (%s)", user);
session.replaceDialog("/firstRun");
}
}
]);
function readTeamsFromFile() {
return fse.readJsonSync("./data/teams.json");
}
function writeTeamsToFile(teams) {
fse.outputJsonSync("./data/teams.json", teams);
}
function timeToString(time) {
return pad(parseInt(time / 60 / 60 % 24)) + ":" + pad(parseInt(time / 60) % 60)
}
function pad(num) {
var s = "0" + num;
return s.substr(s.length - 2);
}
我们在第二个参数数组中提供了两个函数,这些函数将被顺序调用。 用户提供对第一个的响应后,将调用第二个。 在这种情况下,我们使用builder.Prompts.text(session, message))
提示用户输入名称,然后在下一个中,通过使用团队名称搜索JSON处理提供的团队名称。 如果找到了团队名称,我们会将用户的名称添加到JSON并发送一条消息,通知用户他现在已经注册,并会在Scrum时间提示。
除了/ firstRun对话框,我们还有一些帮助程序功能。
readTeamsFromFile()
将从JSON readTeamsFromFile()
文件返回一个JSON对象。
writeTeamsTofile()
将对象作为参数(在我们的示例中为JSON团队)并将其写回到磁盘。
timeToString
将UNIX时间戳记作为参数,并以字符串形式返回解析的时间。
pad
用于在字符串后附加零(例如1小时3分钟应为01:30,而不是1:30)。
将前面的两个代码段添加到我们的bot/app.js
,以及下面的代码以包含npm中的fs-extra
库,让我们尝试一下。
var restify = require("restify"),
builder = require("botbuilder"),
fse = require("fs-extra");
通过仿真器发送消息之前,请确保退出仿真器并重新启动它(仿真器的Delete User Data功能有一个错误)。
现在,您可以进入data/teams.json
文件,您将看到我们已将仿真器用户的地址另存为一个对象。
{
"alpha": {
"members": {
"user": {
"address": {
"id": "3hk7agejfgehaaf26",
"channelId": "emulator",
"user": {
"id": "default-user",
"name": "User"
},
"conversation": {
"id": "5kaf6861ll4a7je6"
},
"bot": {
"id": "default-bot"
},
"serviceUrl": "http://localhost:54554",
"useAuth": false
}
}
},
"time": 0
}
}
我们还应该使用根对话框来做一些更有意义的事情。 用户完成/firstRun
,我们应该输出某种消息以使用户知道正在发生的事情。
bot.dialog("/", function(session) {
// this is a hack in order to avoid this issue
// https://github.com/Microsoft/BotBuilder/issues/1837
if (!session.userData.team || !session.userData.user) {
session.replaceDialog("/firstRun");
} else {
session.send("Hello there, it's not yet scrum time. I'll get back to you later.");
}
});
首次运行的中间件只是普通的中间件,与其他任何中间件一样,默认情况下在框架中实现。 我们还可以创建一个自定义的中间件功能。 在与Skype用户聊天期间,对话ID可能会更改,因此,我们希望在从用户收到的每条消息上更新地址(包含对话ID)。 该地址将随每条消息一起传递,因此让我们将其添加到我们的app.js
bot.use({
botbuilder: function (session, next) {
if (session.userData.team && session.userData.user) {
var teams = readTeamsFromFile();
teams[session.userData.team].members[session.userData.user].address = session.message.address;
writeTeamsToFile(teams);
}
next();
}
});
我们通过使用UniversalBot
类的use
函数添加中间件。 它必须包含一个带有botbuilder
键的对象,该对象的值是一个带有两个参数的函数:会话和next
函数。
我们通过检查会话的userData对象中是否设置了team和user变量来检查是否已经注册了该用户。 如果是,请使用新地址更新JSON文件中的地址。
下一步是添加一个功能,该功能将每隔x秒检查是否有一个团队的每日Scrum会议时间到了。 在会议即将召开的情况下,如果我们有地址(用户已通过“ / firstRun”注册),则通过与团队中的每个成员发起对话来开始“ / dailyScrum”路线。 如果没有地址,那么很遗憾,我们必须跳过此用户,仅在第一次运行完成时提示他们。
setInterval(function() {
var teams = readTeamsFromFile();
Object.keys(teams).forEach(function(team) {
if (shouldStartScrum(team)) {
teamsTmp[team] = { members: {} };
Object.keys(teams[team].members).forEach(function(member) {
if (teams[team].members[member].address) {
bot.beginDialog(teams[team].members[member].address, "/dailyScrum", {team, member});
}
});
}
});
}, 3 * 1000);
function shouldStartScrum(team) {
var teams = readTeamsFromFile();
if (teams[team].time < 24 * 60 * 60 && getTimeInSeconds() > teams[team].time) {
var nextTime = Math.round(new Date().getTime()/1000) - getTimeInSeconds() + 24 * 60 * 60 + teams[team].time;
teams[team].time = nextTime;
writeTeamsToFile(teams);
return true;
} else if (Math.round(new Date().getTime()/1000) > teams[team].time) {
var nextTime = 24 * 60 * 60 + teams[team].time;
teams[team].time = nextTime;
writeTeamsToFile(teams);
return true;
}
return false;
}
function getTimeInSeconds() {
var d = new Date();
return d.getHours() * 60 * 60 + d.getMinutes() * 60;
}
我们还必须在文件顶部添加teamsTmp
全局变量,以便将团队中每个成员的答案保留在内存中以生成报告。
var teamsTmp = {};
请注意shouldStartScrum
函数,该函数检查时间戳是否在JSON文件中,该文件充当我们在Electron配置程序和bot之间的存储和链接。 我不建议将其用于生产环境。 这仅是为了本教程的目的,是为了显示Bot Framework的功能而制作一个简单的调度程序。
到目前为止,我们已经学到了很多东西,很容易直接添加另一个带有三个问题的瀑布对话框,并将每个答案的数据保存到一个临时变量中,以便稍后我们可以生成报告。 这是将由先前创建的计时器启动的对话框。
/* Add a dailyScrum dialog, which is called when it's a time for a daily scrum meeting, prompting the user in a waterfall fashion dialog */
bot.dialog("/dailyScrum", [
// 1st question of the daily
function (session) {
builder.Prompts.text(session, "What did you do yesterday?");
},
/* After the users answer the 1st question, the waterfall dialog progresses to the next function, with the 2nd question, but checking that the input for the previous question was not an empty string. If yes return the user to the first question by calling replaceDialog */
function(session, results) {
if (results.response.length > 0) {
teamsTmp[session.userData.team].members[session.userData.user] = { q1: results.response };
builder.Prompts.text(session, "What will you do today?");
} else {
session.send("It can't be that you did nothing %s! Let's try this again.", session.userData.user);
session.replaceDialog("/dailyScrum");
}
},
// 3rd question
function(session, results) {
teamsTmp[session.userData.team].members[session.userData.user].q2 = results.response ;
builder.Prompts.text(session, "Are there any impediments in your way?");
},
/* Finalize and schedule a report for the user. After the user has answered the third and last daily scrum question, set the isDone variable for that user to true */
function(session, results) {
teamsTmp[session.userData.team].members[session.userData.user].q3 = results.response;
teamsTmp[session.userData.team].members[session.userData.user].isDone = true;
session.send("Got it! Thank you. When all the members finished answering you will receive a summary.");
/* If the user is the first to finish for the team, create a checker function for the whole team, which
will periodically check whether everyone from the team finished, if yes, send all the users in the team
a report */
if (!teamsTmp[session.userData.team].checker) {
teamsTmp[session.userData.team].checker = setInterval(function() {
if (isEverybodyDone(session.userData.team)) {
teamsTmp[session.userData.team].isDone = true;
clearInterval(teamsTmp[session.userData.team].checker);
var teams = fse.readJsonSync("./data/teams.json");
Object.keys(teamsTmp[session.userData.team].members).forEach(function(member) {
bot.beginDialog(teams[session.userData.team].members[member].address, "/report", { report: createReport(session.userData.team) });
});
session.endDialog();
}
}, 1000);
}
session.endDialog();
}
]);
function isEverybodyDone(team) {
var everybodyDone = true;
Object.keys(teamsTmp[team].members).forEach(function (x) {
if (!teamsTmp[team].members[x].isDone) {
everybodyDone = false;
}
});
return everybodyDone;
}
function createReport(team) {
// change to members
var report = "_"+ team + "_
";
report += "___________
";
Object.keys(teamsTmp[team].members).forEach(function(member) {
report += "**User:** " + member + "
";
report += "**What did " + member + " do yesterday:** " + teamsTmp[team].members[member].q1 + "
";
report += "**What will " + member + " do today:** " + teamsTmp[team].members[member].q2 + "
";
report += "**Impediments for " + member + ":** " + teamsTmp[team].members[member].q3 + "
";
report += "___________
";
});
return report;
}
要格式化消息,可以使用markdown。
将其添加到bot.use(builder.Middleware.firstRun ...
请注意,在每日Scrum对话的末尾,我们使用setInterval()
添加了另一个函数,该函数在团队的第一个成员完成时将开始跟踪团队中的其他所有人是否都已完成回答。 完成每个人的工作后,它将与每个团队成员开始一个新的对话框,并向他们发送生成的报告,该报告将添加为我们的最后一个对话路径。
bot.dialog("/report", function(session, args) {
session.send(args.report);
session.endDialog();
});
请注意,我们将报表作为参数传递给begin对话框函数,然后可以从调用的对话框中的args参数中再次读取该报表。
现在该尝试一下了。 我建议您退出并重新启动仿真器和bot脚本,以确保重置用户数据并且脚本中的最新代码正在运行。
此外,请在JSON文件中更改Scrum的时间,以确保触发会议,而不是等待先前保存的下一次时间。
尝试对机器人说些什么,它会提示您输入团队名称。
启动模拟器或类似操作时,scrum时间已“过去”,因此,如果模拟器没有立即提示您出现问题,请设置时间(直接在JSON文件中或通过Electron配置器)设为0,这将迫使漫游器今天再次开始会议。
更改此设置后,应该立即通过3步瀑布式每日Scrum对话框提示您。
为了与多个用户一起尝试,我们必须将其部署在能够通过SSL进行服务的服务器上,因为这是Microsoft Bot Directory的要求。
我们只是真正地了解了MBF所能提供的功能。 以下是值得进一步研究的几件事,可以使您的机器人更上一层楼。
Microsoft Bot Framework提供的功能远不止于此。 一些有趣的事情包括LUIS(语言理解智能服务) ,该语言使用从Cortana和BING获得的数据来生成试图理解用户想要说的AI的人工智能。
一个更简单的例子是意图对话框,它与我们使用的普通对话框相似,但是代替路由,它们使用了正则表达式作为第一个参数。 基于正则表达式,您可以尝试发现用户的意图,并对识别出的意图进行一些特定的处理。 例如:
// example from https://docs.botframework.com/en-us/node/builder/chat/IntentDialog/
var intents = new builder.IntentDialog();
bot.dialog("/", intents);
intents.matches(/^echo/i, [
function (session) {
builder.Prompts.text(session, "What would you like me to say?");
},
function (session, results) {
session.send("Ok... %s", results.response);
}
]);
我发现非常有用的是Microsoft提供的示例存储库:
https://github.com/Microsoft/BotBuilder-Samples
我们已经介绍了Electron,Scrum,bot框架的对话框堆栈,对话框的瀑布类型,消息传输中间件的基础知识,以及如何在没有用户初始请求的情况下与用户随机地发起对话框。
感谢您关注本教程。 将来我们会看到越来越多的聊天机器人(希望不会太多吗?!)。 如果您有任何意见,建议或问题,请在下面发表评论。
本文由Vildan Softic和Camilo Reyes进行了同行评审。 感谢所有SitePoint的同行评审员使SitePoint内容达到最佳状态!
翻译自: https://www.sitepoint.com/skype-bot-electron-microsoft-bot-framework/
electron 图标制作