Skip to content

Commit

Permalink
Appsettings load refactoring. Adaptive card templating.
Browse files Browse the repository at this point in the history
Appsettings load refactoring. Adaptive card templating.
  • Loading branch information
hinojosachapel authored Feb 23, 2020
2 parents 38e517c + d382e76 commit ab64b15
Show file tree
Hide file tree
Showing 19 changed files with 299 additions and 210 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@ build
*.env
private
.DS_Store
appsettings.json
79 changes: 28 additions & 51 deletions javascript_nodejs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,50 +20,35 @@
- [Create a QnA Maker service][15]
1. After creating the **QnA Maker** service, create a knowledge base using the `CoreplusKB.tsv` file located in the `cognitiveModels` folder of the project. Use this **.tsv** file to populate your KB. Then train and publish your model, and obtain the values to connect your bot to the knowledge base.

- Update the **.bot** file `development.bot` located in the `javascript_nodejs/src/config` folder with the missing values for LUIS and QnA Maker services.
- Create the **appsettings.json** file in the `javascript_nodejs/src` folder with the missing values for your bot app, LUIS and QnA Maker services. You will need Cosmos DB keys only when deploying to Azure.
```javascript
{
"name": "coreplus",
"description": "",
"services": [
{
"type": "endpoint",
"id": "1",
"name": "endpoint",
"appId": "",
"appPassword": "",
"endpoint": "http://localhost:3978/api/messages"
},
{
"type": "luis",
"id": "20",
"name": "LUIS-en-US",
"appId": "<YOUR_APP_ID>",
"authoringKey": "<YOUR_AUTHORING_KEY>",
"subscriptionKey": "<YOUR_AUTHORING_KEY>",
"version": "0.1",
"region": "<YOUR_REGION>"
},
{
"type": "qna",
"id": "30",
"name": "QNA-en-US",
"kbId": "<Your_Knowledge_Base_Id>",
"subscriptionKey": "",
"endpointKey": "<Your_Endpoint_Key>",
"hostname": "https://your-qnamaker-app-name.azurewebsites.net/qnamaker"
}
],
"padlock": "",
"version": "2.0"
"microsoftAppId": "<YOUR_APP_ID>",
"microsoftAppPassword": "<YOUR_APP_PASSWORD>",
"appInsights": {
"instrumentationKey": ""
},
"LUIS-en-US": {
"appId": "<YOUR_APP_ID>",
"authoringKey": "<YOUR_AUTHORING_KEY>",
"subscriptionKey": "<YOUR_AUTHORING_KEY>",
"endpoint": "https://your-region.api.cognitive.microsoft.com"
},
"QNA-en-US": {
"kbId": "<YOUR_KNOWLEDGE_BASE_ID>",
"subscriptionKey": "<YOUR_SUBSCRIPTION_KEY>",
"endpointKey": "<YOUR_ENDPOINT_KEY>",
"hostname": "https://your-qnamaker-app-name.azurewebsites.net/qnamaker"
},
"cosmosDb": {
"serviceEndpoint": "https://your-cosmosdb-account-name.documents.azure.com:443/",
"authKey": "<YOUR_AUTHORING_KEY>",
"databaseId": "<YOUR_DATABASE_ID>",
"collectionId": "<YOUR_COLLECTION_ID>"
},
"publicResourcesUrl": "http://localhost:3978"
}
```

- From inside the development environment, create the `.env` file located in the `javascript_nodejs/src/config` folder with the following content:
```bash
botFileSecret=""
publicResourcesUrl="http://localhost:3978"
```

- Navigate to the `javascript_nodejs` folder and run the following npm commands to install modules and start the bot:
```bash
Expand All @@ -74,16 +59,12 @@
# Testing the bot using Bot Framework Emulator **v4**
[Bot Framework Emulator][5] is a desktop application that allows bot developers to test and debug their bots on localhost or running remotely through a tunnel.

- Install the Bot Framework Emulator version 4.2.0 or greater from [here][6]
- Install the Bot Framework Emulator version 4.5.0 or greater from [here][6]

## Connect to the bot using Bot Framework Emulator **v4**
- Launch Bot Framework Emulator
- File -> Open Bot Configuration
- Navigate to `javascript_nodejs/src/config` folder
- Select `development.bot` file

# About the .bot file
With the 4.3 release of the Bot Framework, Microsoft moved away from using .bot files. The .bot file [has been deprecated](https://docs.microsoft.com/en-us/azure/bot-service/bot-file-basics?view=azure-bot-service-4.0&tabs=js). The new recommended solution for managing resources is to use appsettings.json or .env file instead of the .bot file. So, I'll be updating the project in the near future accordingly.
- File -> Open Bot
- Enter a Bot URL of `http://localhost:3978/api/messages`, <YOUR_APP_ID> and <YOUR_APP_PASSWORD>.

# Further reading
- [CorePlus: a Microsoft Bot Framework v4 template][50]
Expand All @@ -92,16 +73,13 @@ With the 4.3 release of the Bot Framework, Microsoft moved away from using .bot
- [Azure Bot Service Introduction][21]
- [Azure Bot Service Documentation][22]
- [Deploying Your Bot to Azure][40]
- [msbot CLI][9]
- [Azure Portal][10]
- [Restify][30]
- [dotenv][31]

[1]: https://dev.botframework.com
[4]: https://nodejs.org
[5]: https://github.com/microsoft/botframework-emulator
[6]: https://github.com/Microsoft/BotFramework-Emulator/releases
[9]: https://github.com/Microsoft/botbuilder-tools/tree/master/packages/MSBot
[10]: https://portal.azure.com
[11]: https://www.luis.ai
[12]: https://www.qnamaker.ai
Expand All @@ -115,7 +93,6 @@ With the 4.3 release of the Bot Framework, Microsoft moved away from using .bot
[21]: https://docs.microsoft.com/azure/bot-service/bot-service-overview-introduction?view=azure-bot-service-4.0
[22]: https://docs.microsoft.com/azure/bot-service/?view=azure-bot-service-4.0
[30]: https://www.npmjs.com/package/restify
[31]: https://www.npmjs.com/package/dotenv
[32]: https://docs.microsoft.com/azure/bot-service/bot-builder-basics?view=azure-bot-service-4.0
[40]: https://docs.microsoft.com/en-us/azure/bot-service/bot-builder-deploy-az-cli?view=azure-bot-service-4.0
[50]: https://www.codeproject.com/Articles/4254785/CorePlus-a-Microsoft-Bot-Framework-v4-template
5 changes: 5 additions & 0 deletions javascript_nodejs/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions javascript_nodejs/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
"url": "https://github.com/hinojosachapel/CorePlus"
},
"dependencies": {
"adaptivecards-templating": "^0.1.1-alpha.0",
"botbuilder": "^4.7.1",
"botbuilder-ai": "^4.7.1",
"botbuilder-azure": "^4.7.1",
Expand Down
26 changes: 0 additions & 26 deletions javascript_nodejs/src/config/appsettings.json

This file was deleted.

8 changes: 8 additions & 0 deletions javascript_nodejs/src/dialogs/shared/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
// Licensed under the MIT License.

const { CardFactory } = require('botbuilder');
const ACData = require('adaptivecards-templating');
const localizer = require('i18n');

class Utils {
Expand Down Expand Up @@ -122,6 +123,13 @@ class Utils {
static shouldShowTyping() {
return this.getRandomInt(0, 100) < 30;
}

static adaptiveCardDataBind(templatePayload, dataContext) {
const template = new ACData.Template(templatePayload);
const context = new ACData.EvaluationContext();
context.$root = dataContext;
return CardFactory.adaptiveCard(template.expand(context));
}
}

/**
Expand Down
19 changes: 13 additions & 6 deletions javascript_nodejs/src/dialogs/welcome/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -48,18 +48,25 @@ class WelcomeDialog extends ComponentDialog {
}

getWelcomeCard(locale) {
welcomeCard.body[0].url = process.env.publicResourcesUrl + '/public/welcome_logo.png';
welcomeCard.body[1].text = localizer.gettext(locale, 'welcome.tittle');
const welcomeLogoUrl = process.env.publicResourcesUrl + '/public/welcome_logo.png';
const welcomeTittle = localizer.gettext(locale, 'welcome.tittle');

// Restart command should be localized.
const restartCommand = localizer.gettext(locale, 'restartCommand');
welcomeCard.body[2].text = localizer.gettext(locale, 'welcome.subtittle', restartCommand);
const welcomeSubtittle = localizer.gettext(locale, 'welcome.subtittle', restartCommand);

welcomeCard.actions[0].title = localizer.gettext(locale, 'welcome.privacy');
const welcomeAction = localizer.gettext(locale, 'welcome.action');
const language = locale.substring(0, 2);
welcomeCard.actions[0].url = process.env.publicResourcesUrl + '/public/privacy_policy_' + language + '.pdf';
const welcomeActionUrl = process.env.publicResourcesUrl + '/public/privacy_policy_' + language + '.pdf';

const card = Utils.adaptiveCardDataBind(welcomeCard, {
welcomeLogoUrl,
welcomeTittle,
welcomeSubtittle,
welcomeAction,
welcomeActionUrl
});

const card = CardFactory.adaptiveCard(welcomeCard);
return { attachments: [card] };
}
}
Expand Down
10 changes: 5 additions & 5 deletions javascript_nodejs/src/dialogs/welcome/resources/welcomeCard.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,32 +5,32 @@
"body": [
{
"type": "Image",
"url": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQtB3AwMUeNoq4gUBGe6Ocj8kyh3bXa9ZbV7u1fVKQoyKFHdkqU",
"url": "{welcomeLogoUrl}",
"size": "stretch"
},
{
"type": "TextBlock",
"spacing": "medium",
"size": "default",
"weight": "bolder",
"text": "Welcome to Bot Framework!",
"text": "{welcomeTittle}",
"wrap": true,
"maxLines": 0
},
{
"type": "TextBlock",
"size": "default",
"isSubtle": true,
"text": "Now that you have successfully run your bot, follow the links in this Adaptive Card to expand your knowledge of Bot Framework.",
"text": "{welcomeSubtittle}",
"wrap": true,
"maxLines": 0
}
],
"actions": [
{
"type": "Action.OpenUrl",
"title": "text1",
"url": "https://docs.microsoft.com/en-us/azure/bot-service/?view=azure-bot-service-4.0"
"title": "{welcomeAction}",
"url": "{welcomeActionUrl}"
}
]
}
20 changes: 6 additions & 14 deletions javascript_nodejs/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,18 @@
const path = require('path');
const restify = require('restify');
const localizer = require('i18n');
const { readFileSync } = require('fs');

// Import required bot services. See https://aka.ms/bot-services to learn more about the different parts of a bot.
const { BotFrameworkAdapter, MemoryStorage, ConversationState, UserState } = require('botbuilder');
const { LuisRecognizer, QnAMaker } = require('botbuilder-ai');
const { CosmosDbStorage } = require('botbuilder-azure');

// Avoid uploading sensitive information like appsettings.json file to your source code repository.
// .gitignore file contains appsettings.json as an ignored file.
// When creating your bot web app, manually create your server hosted appsettings.json file.
const appsettings = require('./appsettings.json');
process.env.publicResourcesUrl = appsettings.publicResourcesUrl;

// This bot's main dialog.
const { MainDialog } = require('./dialogs/main');
const { CorePlusBot } = require('./bot');
Expand All @@ -34,19 +39,6 @@ const QNA_MAKER_OPTIONS = {
top: 1
};

const appsettingsFile = 'appsettings.json';
let appsettingsPath;
if (NODE_ENV === DEV_ENV) {
// Avoid uploading sensitive information like appsettings.json file to your source code repository.
// Here we store that file inside a Git ignored folder for development purposes.
appsettingsPath = path.join(__dirname, 'config/private', appsettingsFile);
} else {
appsettingsPath = path.join(__dirname, 'config', appsettingsFile);
}

const appsettings = JSON.parse(readFileSync(appsettingsPath, 'UTF8'));
process.env.publicResourcesUrl = appsettings.publicResourcesUrl;

// Create adapter.
// See https://aka.ms/about-bot-adapter to learn more about adapters and how bots work.
const adapter = new BotFrameworkAdapter({
Expand Down
74 changes: 66 additions & 8 deletions javascript_nodejs/src/locales/en-US.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@
"tittle": "👋 Hello, welcome to Bot Framework!",
"subtittle": "If you want to start over, just write \"**%s**\" at any time. Stuck and don't know what to say? Type \"**help**\" and I'll tell you some hints. You may also ask me questions about the trained subject in QnA Maker.",
"privacy": "See my privacy policy",
"readyPrompt": "How can I help you?"
"readyPrompt": "How can I help you?",
"action": "welcome.action"
},
"greeting": {
"namePrompt": "What is your name?",
Expand Down Expand Up @@ -59,13 +60,70 @@
"noThumb": "No 👎"
},
"synonyms": {
"yes": ["yes", "y", "yeah", "yay", "👍", "awesome", "great", "cool", "sounds good", "works for me", "bingo", "go ahead",
"yup", "yes to that", "you're right", "that was right", "that was correct", "that's accurate", "accurate", "ok",
"yep", "that's right", "that's true", "correct", "that's right", "that's true", "sure", "good", "confirm", "thumbs up"],
"no": ["no", "n", "nope", "👎", "ko", "uh-uh", "nix", "nixie", "nixy", "nixey", "nay", "nah", "no way",
"negative", "out of the question", "for foul nor fair", "not", "thumbs down", "pigs might fly", "fat chance",
"catch me", "go fish", "certainly not", "by no means", "of course not", "hardly"],
"cancel": ["cancel", "abort"]
"yes": [
"yes",
"y",
"yeah",
"yay",
"👍",
"awesome",
"great",
"cool",
"sounds good",
"works for me",
"bingo",
"go ahead",
"yup",
"yes to that",
"you're right",
"that was right",
"that was correct",
"that's accurate",
"accurate",
"ok",
"yep",
"that's right",
"that's true",
"correct",
"that's right",
"that's true",
"sure",
"good",
"confirm",
"thumbs up"
],
"no": [
"no",
"n",
"nope",
"👎",
"ko",
"uh-uh",
"nix",
"nixie",
"nixy",
"nixey",
"nay",
"nah",
"no way",
"negative",
"out of the question",
"for foul nor fair",
"not",
"thumbs down",
"pigs might fly",
"fat chance",
"catch me",
"go fish",
"certainly not",
"by no means",
"of course not",
"hardly"
],
"cancel": [
"cancel",
"abort"
]
},
"readyPrompt": "What can I do for you? \r (Choose one or type your own question)",
"profanity": "That hurt my feelings. 😓 If you are stuck, just type \"**help**\" and I'll tell you some hints.",
Expand Down
Loading

0 comments on commit ab64b15

Please sign in to comment.