JavaScript Cheat Sheet

This cheat sheet serves as a quick reference for common JavaScript scripting tasks, focusing on enhancing your bot interactions and automation processes. It covers a range of topics from basic value checks to complex pattern validation.

Some General Things to Know About How Parloa Handles JS

  • return Statements: No return statement is needed to return a storage variable to a block. Unless you define a whole function inside the block, Parloa will return the last variable it "saw". Using a return statement outside of a function to return something to the block will result in an error.

  • Condition Blocks: Function on the if / else if / else principle line by line. The if/else is already built-in — each space in the block is only the code/condition that should evaluate to true or false.

  • Variable Initialization: If your code requires creating (initializing) a JS variable, do it inside a function. If your call flow loops back, or if you try to use the same variable name later, Parloa will throw an error.

Instead of doing this:

Do this:

Using Regex

Please refer to the Using Regular Expressions (Regex) page.

Quick Snippets/Basics

Remove Non-Digits from a String
intent.text.replace(/[^\d]/g, "")

or

intent.text.replace(/\D/g,"")
Remove Duplicates from a List
let newVarName = [];
newVarName = [...new Set(storage.varName)];
newVarName;
Split Customer ID for Readout (every 3 characters)
const groups = storage.tempVSNR.match(/(\d{0,3})(\d{0,3})(\d{0,3})(\d{0,3})(\d{0,3})(\d{0,3})/).slice(1);
"<say-as interpret-as='characters'>" + groups.join("</say-as>, <say-as interpret-as='characters'>") + "</say-as>"
Split Every Character Separately
const groups = storage.tempVSNR.match(/.{1,1}/g);
"<say-as interpret-as='characters'>" + groups.join("</say-as>, <say-as interpret-as='characters'>") + "</say-as>"
Separate Letters and Numbers
const groups = storage.tempVSNR.match(/\d+|\D+/g);
"<say-as interpret-as='characters'>" + groups.join("</say-as>, <say-as interpret-as='characters'>") + "</say-as>"

Array Operations

Check Overlap Between Two Arrays
storage.someListOfOptions.filter(value => storage.someListOfCandidates.includes(value)).length > 0
Return Overlapping Elements Between Two Arrays
storage.someListOfOptions.filter(value => storage.someListOfCandidates.includes(value))

Miscellaneous

Get Call Duration

Record the call start time:

new Date().getTime()

Calculate call duration:

let ms = new Date().getTime() - storage.callStartTime;
let callDuration = new Date(ms).toISOString().slice(11, 19);
callDuration;
Format Date to a Regional Standard
let dateString = "2023-10-30T11:02:35.000+0000";
new Date(dateString).toLocaleDateString('en-US')

More Complex Operations with Strings

Check if a String Includes Specific Values
// For one value
intent.text.includes("YourText")

// For multiple values
["text1", "text2", "text3"].some(textItem => intent.text.includes(textItem))
Replace Values in a String
const valuesToReplace = ["Birnen", "GrÃŧnen"];
const replacementValue = "BÃļnen";
valuesToReplace.forEach(value => intent.text = intent.text.replace(value, replacementValue));
Multiple Value Replacement in a String
function clean_up_utterance(utterance) {
  let replacements = {
      "1": ["uno", "una"],
      "2": ["due"],
      "3": ["tre"],
      "4": ["quattro"]
      // etc.
  };

  for (let option of Object.keys(replacements)) {
    for (let i=0; i<replacements[option].length; i++) {
        let replaceMe = replacements[option][i]
        if (utterance.toLowerCase().split(" ").includes(replaceMe)) {
            utterance = utterance.toLowerCase().replace(replaceMe, option);
        }
    }
  }
  return utterance;
}

Array Manipulations

Join List of Strings into a Comma-Separated String
storage.listVariableName.join(",")
Split Comma-Separated String into a List
storage.listVariableName.split(",")
Loop Through a List of Items
let sttCands = [];
for (i=0; i<stt.candidates.length; i++) {
    sttCands.push(stt.candidates[i]["text"]);
}
sttCands;

Advanced Array Operations

Read a List Slot with "and" Before the Last Element
ListOfThings.splice(-2, "and")
Generate Sentences for Each List Item
let readMe = [];
for (i=0; i < storage.ListOfThings.length; i++) {
    let nextString = "Slot " + i + " ist vom Typ " + slotName + " und hat den Wert " + slotValue ;
    readMe.push(nextString)
}
readMe
Add Recognized Slots to a Variable Without Individual Variables
if (storage.ListOfAllSlots) {
    storage.ListOfAllSlots.append(intent.rawPlatformRequestBody.slots)
} else {
    intent.rawPlatformRequestBody.slots
}

String and Variable Manipulations

Trim Spaces from a Variable
storage.varName.trim()
intent.text.trim()
Value Content Check

Purpose: Prevent errors from undefined or null values.

Example: To ensure a variable, such as insuranceNumber, is not empty:

if (storage.insuranceNumber) {
    // Value is set
}

To check if a specific slot, such as number, is set:

if (slots.number) {
    // Slot value is set
}
String Length Verification

Purpose: Validate the length of string variables.

Example:

// Check if insuranceNumber has a fixed length of 5
storage.insuranceNumber && storage.insuranceNumber.length == 5

// Check if insuranceNumber has a minimum length of 5
storage.insuranceNumber && storage.insuranceNumber.length >= 5
Pattern Validation

Purpose: Test if input matches a Regular Expression (RegEx) pattern.

Example: To match a pattern like 'A' followed by 2 digits (for example, A-12):

intent.rawPlatformRequestBody.text.match(/\bA[- ]?\d{2}\b/i)

Regular expressions resources: RegexOne, Regex101

Pattern-Based Input Check

Purpose: Validate patterns like contract numbers.

Example: Testing a pattern like A-2357744:

function checkContractNumber(text) {
    const vsnrRegex = /([A-Z][ -]?)(\d+ ?)+/ig;
    if (vsnrRegex.test(text)) {
        const match = vsnrRegex.exec(text);
        let startLetters = match[1].replace(/[^A-z]/g, '');
        const numbers = match[2].replace(/\D/g, "");
        return `${startLetters}-${numbers}`;
    }
    return "";
}
// Example usage:
checkContractNumber(intent.rawPlatformRequestBody.text)
Read Out Numbers Slower

Purpose: Control the speed of neural voice when reading numbers.

  • Implicit Breaks: Add a break tag between each character:

    storage.characters.split("").join(", ");
  • Explicit Breaks: Use break tags and SSML for each character:

    storage.characters.split('')
        .map(i => `<say-as interpret-as="characters">${i}</say-as>`)
        .join('<break strength="weak"/>');
Extracting Called Number from SIP Invite Headers

Purpose: Retrieve the called number from the To field in SIP headers.

Example:

const toHeader = platform.sipInviteHeaders['To'];
const toNumberMatch = toHeader.match(/<sip:(\+\d+)@/);
toNumberMatch && toNumberMatch[1];
Clean DTMF Input for Digits Only

Purpose: Process only digit characters from DTMF input.

Example:

slots.dtmf && slots.dtmf.replace(/\D/g, '')
Fix DTMF Input Duplication

Purpose: Handle cases where DTMF input is duplicated.

Strategies:

  • All Digits Doubled:

    let result;
    if (slots.dtmf) {
        const pairResult = slots.dtmf.match(/.{1,2}/g);
        if (pairResult.every(item => item.length == 2 && item[1] == item[0])) {
            result = pairResult.map(i => i[0]).join("");
        } else {
            result = slots.dtmf;
        }
        result = result.replace(/\D/g, "");
    }
  • Some Digits Doubled:

    var TARGET_LENGTH = 8;
    function clean(dtmfDigit) {
        for (var i = 0; i < dtmfDigit.length; i++) {
            if (dtmfDigit[i] == dtmfDigit[i + 1] && dtmfDigit.length > TARGET_LENGTH) {
                dtmfDigit = dtmfDigit.substring(0, i) + dtmfDigit.substring(i + 1);
            }
        }
        return dtmfDigit;
    }
    if (slots.dtmf) {
        var dtmf = slots.dtmf.replace(/\D/g, "");
        clean(dtmf);
    }

Last updated