Build a Violet App and Connect It to Salesforce

Create a Script to Tell You About Game Nights

In order to make our Violet script talk to our Salesforce data, you have to set up a connected app in your Salesforce Playground. This connected app gives you information that connects Violet back to Salesforce. We build a Node.js–based Heroku app that runs our Violet script and sends information back to Salesforce via our connected app.

Create a Connected App in Your Playground

  1. Click Gear icon to access Setup in Lightning Experience. and select Setup.
  2. In the Quick Find box search for App Manager.
  3. Click App Manager.
  4. Click New Connected App.
  5. Name your app Violet App.
  • The Api Name automatically generates Violet_App.
  1. Fill in your email address in the contact Email.
  2. Check the Enable OAuth Settings box.
  3. Set the Callback URL to https://login.salesforce.com/services/oauth2/callback.
  4. Move all Available OAuth Scopes to Selected OAuth Scopes.
  5. Click Save.

You will receive the following message: Allow from 2–10 minutes for your changes to take effect on the server before using the connected app.

  1. Click Continue.
  2. On the Connected App page of your Violet App, copy and save your Consumer Key and Consumer Secret. You need these for the application.

Write the Script

In order to make our app work we need two files, and we are going to place them into a folder for ease of use. 

  1. Navigate to the folder on your Desktop called Violet-App that you created previously.
  2. Open the text editor of your choice. We recommend VS (Visual Studio) Code.
  3. Create a new file and copy and paste the following code.
var violet = require('violet').script();

///////////////////////////////////
// Integration and Business Logic
///////////////////////////////////

// Setup Store
var violetStoreSF = require('violet/lib/violetStoreSF')(violet);

// Utilities
var monthNames = [
    "January", "February", "March", "April", "May", "June",
    "July", "August", "September", "October", "November", "December"
  ];
var weekDays = {
  sunday: 0,
  monday: 1,
  tuesday: 2,
  wednesday: 3,
  thursday: 4,
  friday: 5,
  saturday: 6
}
var getDay = (dateTime)=>{
  return `${dateTime.getDate()} ${monthNames[dateTime.getMonth()]}`;
};
var getTime = (dateTime)=>{
  var hh = dateTime.getHours();
  var mm = dateTime.getMinutes();
  var ampm = 'am';
  if (hh>12) {
    hh-=12;
    ampm = 'pm';
  }
  if (mm==0) {
    mm = '';
  } else if (mm<10) {
    mm = 'Oh ' + mm; // Zero is pronounced as Oh when saying the time
  }
  return `${hh} ${mm} ${ampm}`;
};
var calcDateInFuture = (dayOfWeekStr, timeInPMStr)=>{
  var dt = new Date();

  var dayOfWeek = weekDays[dayOfWeekStr.toLowerCase()]
  if (dayOfWeek < dt.getDay()) dayOfWeek += 7;

  dt.setDate(dt.getDate() + dayOfWeek - dt.getDay());

  dt.setHours(parseInt(timeInPMStr) + 12);
  dt.setMinutes(0);
  dt.setSeconds(0);
  dt.setMilliseconds(0);

  return dt;
};

// Hook up the Script
var app = {
  getPastGameNights: (response)=>{
    return response.load({
      query: 'Id, Duration__c, Food__c, Game__c, Name, Start_Time__c FROM Game_Night__c WHERE Start_Time__c < TODAY'
    }).then((results)=>{
      if (results.length == 0) {
        response.say(`Sorry, I did not have anything scheduled`);
      } else {
        var dt = new Date(results[0].get('start_time__c'));
        response.say(`I had a game night scheduled on ${getDay(dt)} at ${getTime(dt)} where ${results[0].get('game__c')} was played`);
      }
    });
  },
  getUpcomingGameNights: (response)=>{
    return response.load({
      query: 'Id, Duration__c, Food__c, Game__c, Name, Start_Time__c FROM Game_Night__c WHERE Start_Time__c >= TODAY'
    }).then((results)=>{
      if (results.length == 0) {
        response.say(`Sorry, I do not have anything scheduled`);
      } else {
        var dt = new Date(results[0].get('start_time__c'));
        response.say(`I have a game night scheduled on ${getDay(dt)} at ${getTime(dt)} to play ${results[0].get('game__c')}`);
      }
    });
  },
}

///////////////////////////////////
// The Voice Script
///////////////////////////////////

violet.addInputTypes({
  "day": {
    type: "dayType",
    values: ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday"]
  },
  "time": "number",
  "duration": "number",
  "game": "phrase",
  "food": "phrase",
});

violet.addFlowScript(`
<app>
  <choice id="launch">
    <expecting>What can you do</expecting>
    <say>I can help you with planning Game Nights</say>
  </choice>

  <choice id="list">
    <expecting>What game nights have already been planned</expecting>
    <say>Sure</say>
    <decision>
      <prompt>Would you like to hear of game nights that are upcoming or in the past</prompt>
      <choice>
        <expecting>{In the|} past</expecting>
        <resolve value="app.getPastGameNights(response)"/>
      </choice>
      <choice>
        <expecting>Upcoming</expecting>
        <resolve value="app.getUpcomingGameNights(response)"/>
      </choice>
    </decision>
  </choice>

  <choice id="update">
    <expecting>Update</expecting>
    <expecting>Delete</expecting>
    <say>...</say>
  </choice>

</app>`, {app});

There is a lot happening here! Let’s take a quick look.

  • You start by defining all utilities.
// Setup Store
var violetStoreSF = require('violet/lib/violetStoreSF')(violet);

// Utilities
var monthNames = [
    "January", "February", "March", "April", "May", "June",
    "July", "August", "September", "October", "November", "December"
  ];
var weekDays = {
  sunday: 0,
  monday: 1,
  tuesday: 2,
  wednesday: 3,
  thursday: 4,
  friday: 5,
  saturday: 6
}
var getDay = (dateTime)=>{
  return `${dateTime.getDate()} ${monthNames[dateTime.getMonth()]}`;
};
var getTime = (dateTime)=>{
  var hh = dateTime.getHours();
  var mm = dateTime.getMinutes();
  var ampm = 'am';
  if (hh>12) {
    hh-=12;
    ampm = 'pm';
  }
  if (mm==0) {
    mm = '';
  } else if (mm<10) {
    mm = 'Oh ' + mm; // Zero is pronounced as Oh when saying the time
  }
  return `${hh} ${mm} ${ampm}`;
};
var calcDateInFuture = (dayOfWeekStr, timeInPMStr)=>{
  var dt = new Date();

  var dayOfWeek = weekDays[dayOfWeekStr.toLowerCase()]
  if (dayOfWeek < dt.getDay()) dayOfWeek += 7;

  dt.setDate(dt.getDate() + dayOfWeek - dt.getDay());

  dt.setHours(parseInt(timeInPMStr) + 12);
  dt.setMinutes(0);
  dt.setSeconds(0);
  dt.setMilliseconds(0);

  return dt;
};
  • Then the code defines two main functions: getPastGameNights and getUpcomingGameNights.
  • Next you define your conversational script: {app} gives the script access to the app object and the code above.

With Violet, you can customize the functions to fetch all kinds of information. But for now the code is focused on these two—either nothing is scheduled or there is information about a game night. 

Finally, the script—this is where you define what Violet is expecting to hear, and then what Violet says in response or what Violet prompts. For instance, if you ask, “What can you do?” Violet lets you know, “I can help you with planning Game Nights.” 

  1. Save the file as gameNight.js.
  2. Create a new file and copy and paste the following code.
'use strict';

var violetSrvr = require('violet/lib/violetSrvr')('/violet');
violetSrvr.listAppsAt('/');
var srvrInstance = violetSrvr.createAndListen(process.env.PORT || 8080);

violetSrvr.loadScript('gameNight.js', 'trailhead');

console.log('Waiting for requests...');
  1. Save the file as server.js.

Now that you have your code in order, you’ve created a node app! Let’s deploy your new app and test it.

Deploy and Test

Now that the script is ready, the next step is to deploy our application.

From your terminal/command prompt, navigate to the directory that holds the node app which you created earlier. The app should be in a folder named Violet-App that has been saved to your desktop.

cd Desktop/Violet-App

 You should see something like:

computerName:Violet-App

If you are on a Mac or Unix based computer enter the following commands in the terminal:

export V_SFDC_CLIENT_ID=[Consumer Key from your Connected App] Insert your consumer key from the earlier step where it says "[Consumer key from your Connected App]". Be sure to remove the brackets.

export V_SFDC_CLIENT_SECRET=[Consumer Secret from your Connected App] Insert your consumer secret from the earlier step where it says "[Consumer secret from your Connected App]". Be sure to remove the brackets.

export V_SFDC_USERNAME=[Username] Insert your Username where it says "[Username]". Be sure to remove the brackets.

export V_SFDC_PASSWORD=[Password] Insert your Password where it says "[Password]". Be sure to remove the brackets.

node server.js

If you are on a Windows based computer enter the following commands in the command prompt:

set V_SFDC_CLIENT_ID=[Consumer Key from your Connected App] Insert your consumer key from the earlier step where it says "[Consumer Key from your Connected App]". Be sure to remove the brackets.

set V_SFDC_CLIENT_SECRET=[Consumer Secret from your Connected App] Insert your consumer secret from the earlier step where it says "[Consumer Secret from your Connected App]". Be sure to remove the brackets.

set V_SFDC_USERNAME=[Username] Insert your Username where it says "[Username]". Be sure to remove the brackets.

set V_SFDC_PASSWORD=[Password] Insert your Password where it says "[Password]". Be sure to remove the brackets.

node server.js

Note

Note

You need your hands-on org username and password to complete this step. If you're using a Trailhead Playground, this article shows you how to find your username and reset your password. If you have an authentication error, please add your security token to your password.

If you’ve successfully followed along so far, you should be able to go to your web browser and go to http://localhost:8080/violet/trailhead. This takes you to the start page of your application.

You can try out your script by selecting the intent you’d like to check. Choose Launch: What do you do and click Send Request. In the Response section, you can see Violet respond with <speak>I can help you with planning Game Nights</speak>.

The start page via local host shows the Violet interface on the Test tab with Request and Response options.

You can test the other aspects of your script by selecting other Intents and clicking Send Request.

You’ve successfully built your first Violet application! In the next step, you update the script and deploy and test. You wrap it up with details on how you can deploy it to Heroku and get some next steps to enable you to use it with Alexa or Google Assistant.  

retargeting