From 809fa5bcf393353601ca29145806b14869619ab8 Mon Sep 17 00:00:00 2001 From: patelravi Date: Sun, 24 Mar 2019 23:16:47 +0530 Subject: [PATCH] Added ssml. --- TODO | 12 ++++ lib/rest/utils.js | 129 +++++++++++++++++++++++++++++++++--------- lib/utils/plivoxml.js | 49 +++++++++------- package-lock.json | 16 +++++- package.json | 3 +- test/ssml.js | 21 +++++-- 6 files changed, 179 insertions(+), 51 deletions(-) create mode 100644 TODO diff --git a/TODO b/TODO new file mode 100644 index 0000000..f77b2d4 --- /dev/null +++ b/TODO @@ -0,0 +1,12 @@ + +1. Polly.* + +2. How to validate languages with voice + +3. Male female voices for polly+voice combination + +4. Promise, chain will break + +5. Will childs be there in ssml for validation? + +6. \ No newline at end of file diff --git a/lib/rest/utils.js b/lib/rest/utils.js index 068dc24..ae5f162 100644 --- a/lib/rest/utils.js +++ b/lib/rest/utils.js @@ -3,6 +3,7 @@ import _snakeCase from 'lodash/snakeCase'; import _mapKeys from 'lodash/mapKeys'; import _mapValues from 'lodash/mapValues'; import _map from 'lodash/map'; +import { parseString } from 'xml2js'; function recursivelyRenameObject(object, renameFunc) { if (!(object instanceof Object)) { @@ -54,38 +55,114 @@ export function camelCaseRequestWrapper(requestFunc) { } } -export function validateVoiceForSsml(voice, language) { +export function validateVoiceForSsml(content, voice, language) { - var voiceParts = voice.split('.'); - if (['MAN', 'WOMAN'].indexOf(voice) != -1) { - return { success: true }; - } else if (voiceParts.length != 2 || voiceParts[0] != 'Polly') { - return { - success: false, msg: "Invalid voice " + voice + '.' + return new Promise(function (resolve, reject) { + + var voiceParts = voice.split('.'); + if (['MAN', 'WOMAN'].indexOf(voice) != -1) { + resolve({ success: true }); + return; + } else if (voiceParts.length != 2 || voiceParts[0] != 'Polly') { + resolve({ + success: false, msg: "Invalid voice " + voice + '.' + }); + return; + } + + // If voice is polly, validate accent based on language specified + + // List of valid Polly voices + var languageWiseVoices = { + 'Australian English': ['Nicole', 'Russell'], + 'Brazilian Portuguese': ['Vitória', 'Ricardo'], + 'Canadian French': ['Chantal'], + 'Canadian French': ['Chantal'], + 'Danish': ['Naja', 'Mads'], + 'Dutch': ['Lotte', 'Ruben'], + 'French': ['Léa', 'Céline', 'Mathieu'], + 'German': ['Vicki', 'Hans'], + 'Hindi': ['Aditi'], + 'Icelandic': ['Dóra', 'Karl'], + 'Indian English': ['Raveena ', 'Aditi'], + 'Italian': ['Carla', 'Giorgio'], + 'Japanese': ['Mizuki', 'Takumi'], + 'Korean': ['Seoyeon'], + 'Mandarin Chinese': ['Zhiyu'], + 'Norwegian': ['Liv'], + 'Polish': ['Ewa', 'Maja', 'Jacek', 'Jan'], + 'Portuguese-Iberic': ['Inês', 'Cristiano'], + 'Romanian': ['Carmen'], + 'Russian': ['Tatyana', 'Maxim'], + 'Spanish-Castilian': ['Conchita', 'Enrique'], + 'Swedish': ['Astrid'], + 'Turkish': ['Filiz'], + 'UK English': ['Amy', 'Emma', 'Brian'], + 'US English': ['Joanna', 'Salli', 'Kendra', 'Kimberly', 'Ivy', 'Matthew', 'Justin', 'Joey'], + 'US Spanish': ['Penélope', 'Miguel'], + 'Welsh': ['Gwyneth'], + 'Welsh English': ['Geraint'], }; - } - // If voice is polly, validate accent based on language specified + // Validate supported languages. + if (!languageWiseVoices[language]) { + resolve({ + success: false, msg: "Invalid language." + }); + return; + } - // List of valid Polly voices - var languageWiseVoices = { - 'Australian English': ['Nicole', 'Russell'], - 'Brazilian Portuguese': ['Vitória', 'Ricardo'] - }; + // Validate voice for given language. + if (languageWiseVoices[language].indexOf(voiceParts[1]) == -1) { + console.log('==> voice ‘" + voice + "’ is not valid. Refer for list of supported voices." + }); + return; + } - // Validate supported languages. - if (!languageWiseVoices[language]) { - return { - success: false, msg: "Invalid language." - }; - } + // Validate xml now + var contenxtXml = "" + content + ""; + parseString(contenxtXml, function (err, xmlJson) { + if (err || !xmlJson) { + // console.log('XMl parsing error validation result', err); + resolve({ + success: false, + msg: "Invalid SSML xml structure. Content must be a valid xml. Parsing Error: " + err + }) + } + xmlJson = xmlJson.root; - // Validate voice for given language. - if (languageWiseVoices[language].indexOf(voiceParts[1]) == -1) { - return { - success: false, msg: "XML Validation Error: voice ‘" + voice + "’ is not valid. Refer for list of supported voices." - }; - } + // Validate supported ssml tags + var validXmlTags = ['break', 'emphasis', 'lang', 'p', 'phoneme', 'prosody', 's', 'say-as', 'sub', 'w']; + + var invalidXmlTag = null; + for (var key in xmlJson) { + // console.log('xml json key', key); + if (key !== '_' && key !== '$') { + if (validXmlTags.indexOf(key) == -1) { + invalidXmlTag = key; + break; + } + } + } + + if (invalidXmlTag) { + resolve({ + success: false, + msg: "SSML tag `" + invalidXmlTag + "` is not supported." + }) + return; + } + + resolve({ + success: true + }); + + }); + + }); } diff --git a/lib/utils/plivoxml.js b/lib/utils/plivoxml.js index 894cc5c..4fdfa7b 100644 --- a/lib/utils/plivoxml.js +++ b/lib/utils/plivoxml.js @@ -254,24 +254,6 @@ Response.prototype = { */ addSpeak: function (body, attributes) { - if (!attributes) { - attributes = {}; - } - - // Validate voice first. - if (!attributes.voice) { - attributes.voice = 'WOMAN'; - } - if (!attributes.language) { - attributes.language = 'English'; - } - let validationResult = plivoUtils.validateVoiceForSsml(attributes.voice, attributes.language); - if (!validationResult.success) { - throw new Exceptions.PlivoXMLValidationError(validationResult.msg); - return; - } - // console.log('validation result', validationResult); - // Convert accented characters to numerical references first let accentedCharsList = { "Á": "A", "Ă": "A", "Ắ": "A", "Ặ": "A", "Ằ": "A", "Ẳ": "A", "Ẵ": "A", "Ǎ": "A", "Â": "A", "Ấ": "A", "Ậ": "A", "Ầ": "A", "Ẩ": "A", "Ẫ": "A", "Ä": "A", "Ǟ": "A", "Ȧ": "A", "Ǡ": "A", "Ạ": "A", "Ȁ": "A", "À": "A", "Ả": "A", "Ȃ": "A", "Ā": "A", "Ą": "A", "Å": "A", "Ǻ": "A", "Ḁ": "A", "Ⱥ": "A", "Ã": "A", "Ꜳ": "AA", "Æ": "AE", "Ǽ": "AE", "Ǣ": "AE", "Ꜵ": "AO", "Ꜷ": "AU", "Ꜹ": "AV", "Ꜻ": "AV", "Ꜽ": "AY", "Ḃ": "B", "Ḅ": "B", "Ɓ": "B", "Ḇ": "B", "Ƀ": "B", "Ƃ": "B", "Ć": "C", "Č": "C", "Ç": "C", "Ḉ": "C", "Ĉ": "C", "Ċ": "C", "Ƈ": "C", "Ȼ": "C", "Ď": "D", "Ḑ": "D", "Ḓ": "D", "Ḋ": "D", "Ḍ": "D", "Ɗ": "D", "Ḏ": "D", "Dz": "D", "Dž": "D", "Đ": "D", "Ƌ": "D", "DZ": "DZ", "DŽ": "DZ", "É": "E", "Ĕ": "E", "Ě": "E", "Ȩ": "E", "Ḝ": "E", "Ê": "E", "Ế": "E", "Ệ": "E", "Ề": "E", "Ể": "E", "Ễ": "E", "Ḙ": "E", "Ë": "E", "Ė": "E", "Ẹ": "E", "Ȅ": "E", "È": "E", "Ẻ": "E", "Ȇ": "E", "Ē": "E", "Ḗ": "E", "Ḕ": "E", "Ę": "E", "Ɇ": "E", "Ẽ": "E", "Ḛ": "E", "Ꝫ": "ET", "Ḟ": "F", "Ƒ": "F", "Ǵ": "G", "Ğ": "G", "Ǧ": "G", "Ģ": "G", "Ĝ": "G", "Ġ": "G", "Ɠ": "G", "Ḡ": "G", "Ǥ": "G", "Ḫ": "H", "Ȟ": "H", "Ḩ": "H", "Ĥ": "H", "Ⱨ": "H", "Ḧ": "H", "Ḣ": "H", "Ḥ": "H", "Ħ": "H", "Í": "I", "Ĭ": "I", "Ǐ": "I", "Î": "I", "Ï": "I", "Ḯ": "I", "İ": "I", "Ị": "I", "Ȉ": "I", "Ì": "I", "Ỉ": "I", "Ȋ": "I", "Ī": "I", "Į": "I", "Ɨ": "I", "Ĩ": "I", "Ḭ": "I", "Ꝺ": "D", "Ꝼ": "F", "Ᵹ": "G", "Ꞃ": "R", "Ꞅ": "S", "Ꞇ": "T", "Ꝭ": "IS", "Ĵ": "J", "Ɉ": "J", "Ḱ": "K", "Ǩ": "K", "Ķ": "K", "Ⱪ": "K", "Ꝃ": "K", "Ḳ": "K", "Ƙ": "K", "Ḵ": "K", "Ꝁ": "K", "Ꝅ": "K", "Ĺ": "L", "Ƚ": "L", "Ľ": "L", "Ļ": "L", "Ḽ": "L", "Ḷ": "L", "Ḹ": "L", "Ⱡ": "L", "Ꝉ": "L", "Ḻ": "L", "Ŀ": "L", "Ɫ": "L", "Lj": "L", "Ł": "L", "LJ": "LJ", "Ḿ": "M", "Ṁ": "M", "Ṃ": "M", "Ɱ": "M", "Ń": "N", "Ň": "N", "Ņ": "N", "Ṋ": "N", "Ṅ": "N", "Ṇ": "N", "Ǹ": "N", "Ɲ": "N", "Ṉ": "N", "Ƞ": "N", "Nj": "N", "Ñ": "N", "NJ": "NJ", "Ó": "O", "Ŏ": "O", "Ǒ": "O", "Ô": "O", "Ố": "O", "Ộ": "O", "Ồ": "O", "Ổ": "O", "Ỗ": "O", "Ö": "O", "Ȫ": "O", "Ȯ": "O", "Ȱ": "O", "Ọ": "O", "Ő": "O", "Ȍ": "O", "Ò": "O", "Ỏ": "O", "Ơ": "O", "Ớ": "O", "Ợ": "O", "Ờ": "O", "Ở": "O", "Ỡ": "O", "Ȏ": "O", "Ꝋ": "O", "Ꝍ": "O", "Ō": "O", "Ṓ": "O", "Ṑ": "O", "Ɵ": "O", "Ǫ": "O", "Ǭ": "O", "Ø": "O", "Ǿ": "O", "Õ": "O", "Ṍ": "O", "Ṏ": "O", "Ȭ": "O", "Ƣ": "OI", "Ꝏ": "OO", "Ɛ": "E", "Ɔ": "O", "Ȣ": "OU", "Ṕ": "P", "Ṗ": "P", "Ꝓ": "P", "Ƥ": "P", "Ꝕ": "P", "Ᵽ": "P", "Ꝑ": "P", "Ꝙ": "Q", "Ꝗ": "Q", "Ŕ": "R", "Ř": "R", "Ŗ": "R", "Ṙ": "R", "Ṛ": "R", "Ṝ": "R", "Ȑ": "R", "Ȓ": "R", "Ṟ": "R", "Ɍ": "R", "Ɽ": "R", "Ꜿ": "C", "Ǝ": "E", "Ś": "S", "Ṥ": "S", "Š": "S", "Ṧ": "S", "Ş": "S", "Ŝ": "S", "Ș": "S", "Ṡ": "S", "Ṣ": "S", "Ṩ": "S", "Ť": "T", "Ţ": "T", "Ṱ": "T", "Ț": "T", "Ⱦ": "T", "Ṫ": "T", "Ṭ": "T", "Ƭ": "T", "Ṯ": "T", "Ʈ": "T", "Ŧ": "T", "Ɐ": "A", "Ꞁ": "L", "Ɯ": "M", "Ʌ": "V", "Ꜩ": "TZ", "Ú": "U", "Ŭ": "U", "Ǔ": "U", "Û": "U", "Ṷ": "U", "Ü": "U", "Ǘ": "U", "Ǚ": "U", "Ǜ": "U", "Ǖ": "U", "Ṳ": "U", "Ụ": "U", "Ű": "U", "Ȕ": "U", "Ù": "U", "Ủ": "U", "Ư": "U", "Ứ": "U", "Ự": "U", "Ừ": "U", "Ử": "U", "Ữ": "U", "Ȗ": "U", "Ū": "U", "Ṻ": "U", "Ų": "U", "Ů": "U", "Ũ": "U", "Ṹ": "U", "Ṵ": "U", "Ꝟ": "V", "Ṿ": "V", "Ʋ": "V", "Ṽ": "V", "Ꝡ": "VY", "Ẃ": "W", "Ŵ": "W", "Ẅ": "W", "Ẇ": "W", "Ẉ": "W", "Ẁ": "W", "Ⱳ": "W", "Ẍ": "X", "Ẋ": "X", "Ý": "Y", "Ŷ": "Y", "Ÿ": "Y", "Ẏ": "Y", "Ỵ": "Y", "Ỳ": "Y", "Ƴ": "Y", "Ỷ": "Y", "Ỿ": "Y", "Ȳ": "Y", "Ɏ": "Y", "Ỹ": "Y", "Ź": "Z", "Ž": "Z", "Ẑ": "Z", "Ⱬ": "Z", "Ż": "Z", "Ẓ": "Z", "Ȥ": "Z", "Ẕ": "Z", "Ƶ": "Z", "IJ": "IJ", "Œ": "OE", "ᴀ": "A", "ᴁ": "AE", "ʙ": "B", "ᴃ": "B", "ᴄ": "C", "ᴅ": "D", "ᴇ": "E", "ꜰ": "F", "ɢ": "G", "ʛ": "G", "ʜ": "H", "ɪ": "I", "ʁ": "R", "ᴊ": "J", "ᴋ": "K", "ʟ": "L", "ᴌ": "L", "ᴍ": "M", "ɴ": "N", "ᴏ": "O", "ɶ": "OE", "ᴐ": "O", "ᴕ": "OU", "ᴘ": "P", "ʀ": "R", "ᴎ": "N", "ᴙ": "R", "ꜱ": "S", "ᴛ": "T", "ⱻ": "E", "ᴚ": "R", "ᴜ": "U", "ᴠ": "V", "ᴡ": "W", "ʏ": "Y", "ᴢ": "Z", "á": "a", "ă": "a", "ắ": "a", "ặ": "a", "ằ": "a", "ẳ": "a", "ẵ": "a", "ǎ": "a", "â": "a", "ấ": "a", "ậ": "a", "ầ": "a", "ẩ": "a", "ẫ": "a", "ä": "a", "ǟ": "a", "ȧ": "a", "ǡ": "a", "ạ": "a", "ȁ": "a", "à": "a", "ả": "a", "ȃ": "a", "ā": "a", "ą": "a", "ᶏ": "a", "ẚ": "a", "å": "a", "ǻ": "a", "ḁ": "a", "ⱥ": "a", "ã": "a", "ꜳ": "aa", "æ": "ae", "ǽ": "ae", "ǣ": "ae", "ꜵ": "ao", "ꜷ": "au", "ꜹ": "av", "ꜻ": "av", "ꜽ": "ay", "ḃ": "b", "ḅ": "b", "ɓ": "b", "ḇ": "b", "ᵬ": "b", "ᶀ": "b", "ƀ": "b", "ƃ": "b", "ɵ": "o", "ć": "c", "č": "c", "ç": "c", "ḉ": "c", "ĉ": "c", "ɕ": "c", "ċ": "c", "ƈ": "c", "ȼ": "c", "ď": "d", "ḑ": "d", "ḓ": "d", "ȡ": "d", "ḋ": "d", "ḍ": "d", "ɗ": "d", "ᶑ": "d", "ḏ": "d", "ᵭ": "d", "ᶁ": "d", "đ": "d", "ɖ": "d", "ƌ": "d", "ı": "i", "ȷ": "j", "ɟ": "j", "ʄ": "j", "dz": "dz", "dž": "dz", "é": "e", "ĕ": "e", "ě": "e", "ȩ": "e", "ḝ": "e", "ê": "e", "ế": "e", "ệ": "e", "ề": "e", "ể": "e", "ễ": "e", "ḙ": "e", "ë": "e", "ė": "e", "ẹ": "e", "ȅ": "e", "è": "e", "ẻ": "e", "ȇ": "e", "ē": "e", "ḗ": "e", "ḕ": "e", "ⱸ": "e", "ę": "e", "ᶒ": "e", "ɇ": "e", "ẽ": "e", "ḛ": "e", "ꝫ": "et", "ḟ": "f", "ƒ": "f", "ᵮ": "f", "ᶂ": "f", "ǵ": "g", "ğ": "g", "ǧ": "g", "ģ": "g", "ĝ": "g", "ġ": "g", "ɠ": "g", "ḡ": "g", "ᶃ": "g", "ǥ": "g", "ḫ": "h", "ȟ": "h", "ḩ": "h", "ĥ": "h", "ⱨ": "h", "ḧ": "h", "ḣ": "h", "ḥ": "h", "ɦ": "h", "ẖ": "h", "ħ": "h", "ƕ": "hv", "í": "i", "ĭ": "i", "ǐ": "i", "î": "i", "ï": "i", "ḯ": "i", "ị": "i", "ȉ": "i", "ì": "i", "ỉ": "i", "ȋ": "i", "ī": "i", "į": "i", "ᶖ": "i", "ɨ": "i", "ĩ": "i", "ḭ": "i", "ꝺ": "d", "ꝼ": "f", "ᵹ": "g", "ꞃ": "r", "ꞅ": "s", "ꞇ": "t", "ꝭ": "is", "ǰ": "j", "ĵ": "j", "ʝ": "j", "ɉ": "j", "ḱ": "k", "ǩ": "k", "ķ": "k", "ⱪ": "k", "ꝃ": "k", "ḳ": "k", "ƙ": "k", "ḵ": "k", "ᶄ": "k", "ꝁ": "k", "ꝅ": "k", "ĺ": "l", "ƚ": "l", "ɬ": "l", "ľ": "l", "ļ": "l", "ḽ": "l", "ȴ": "l", "ḷ": "l", "ḹ": "l", "ⱡ": "l", "ꝉ": "l", "ḻ": "l", "ŀ": "l", "ɫ": "l", "ᶅ": "l", "ɭ": "l", "ł": "l", "lj": "lj", "ſ": "s", "ẜ": "s", "ẛ": "s", "ẝ": "s", "ḿ": "m", "ṁ": "m", "ṃ": "m", "ɱ": "m", "ᵯ": "m", "ᶆ": "m", "ń": "n", "ň": "n", "ņ": "n", "ṋ": "n", "ȵ": "n", "ṅ": "n", "ṇ": "n", "ǹ": "n", "ɲ": "n", "ṉ": "n", "ƞ": "n", "ᵰ": "n", "ᶇ": "n", "ɳ": "n", "ñ": "n", "nj": "nj", "ó": "o", "ŏ": "o", "ǒ": "o", "ô": "o", "ố": "o", "ộ": "o", "ồ": "o", "ổ": "o", "ỗ": "o", "ö": "o", "ȫ": "o", "ȯ": "o", "ȱ": "o", "ọ": "o", "ő": "o", "ȍ": "o", "ò": "o", "ỏ": "o", "ơ": "o", "ớ": "o", "ợ": "o", "ờ": "o", "ở": "o", "ỡ": "o", "ȏ": "o", "ꝋ": "o", "ꝍ": "o", "ⱺ": "o", "ō": "o", "ṓ": "o", "ṑ": "o", "ǫ": "o", "ǭ": "o", "ø": "o", "ǿ": "o", "õ": "o", "ṍ": "o", "ṏ": "o", "ȭ": "o", "ƣ": "oi", "ꝏ": "oo", "ɛ": "e", "ᶓ": "e", "ɔ": "o", "ᶗ": "o", "ȣ": "ou", "ṕ": "p", "ṗ": "p", "ꝓ": "p", "ƥ": "p", "ᵱ": "p", "ᶈ": "p", "ꝕ": "p", "ᵽ": "p", "ꝑ": "p", "ꝙ": "q", "ʠ": "q", "ɋ": "q", "ꝗ": "q", "ŕ": "r", "ř": "r", "ŗ": "r", "ṙ": "r", "ṛ": "r", "ṝ": "r", "ȑ": "r", "ɾ": "r", "ᵳ": "r", "ȓ": "r", "ṟ": "r", "ɼ": "r", "ᵲ": "r", "ᶉ": "r", "ɍ": "r", "ɽ": "r", "ↄ": "c", "ꜿ": "c", "ɘ": "e", "ɿ": "r", "ś": "s", "ṥ": "s", "š": "s", "ṧ": "s", "ş": "s", "ŝ": "s", "ș": "s", "ṡ": "s", "ṣ": "s", "ṩ": "s", "ʂ": "s", "ᵴ": "s", "ᶊ": "s", "ȿ": "s", "ɡ": "g", "ᴑ": "o", "ᴓ": "o", "ᴝ": "u", "ť": "t", "ţ": "t", "ṱ": "t", "ț": "t", "ȶ": "t", "ẗ": "t", "ⱦ": "t", "ṫ": "t", "ṭ": "t", "ƭ": "t", "ṯ": "t", "ᵵ": "t", "ƫ": "t", "ʈ": "t", "ŧ": "t", "ᵺ": "th", "ɐ": "a", "ᴂ": "ae", "ǝ": "e", "ᵷ": "g", "ɥ": "h", "ʮ": "h", "ʯ": "h", "ᴉ": "i", "ʞ": "k", "ꞁ": "l", "ɯ": "m", "ɰ": "m", "ᴔ": "oe", "ɹ": "r", "ɻ": "r", "ɺ": "r", "ⱹ": "r", "ʇ": "t", "ʌ": "v", "ʍ": "w", "ʎ": "y", "ꜩ": "tz", "ú": "u", "ŭ": "u", "ǔ": "u", "û": "u", "ṷ": "u", "ü": "u", "ǘ": "u", "ǚ": "u", "ǜ": "u", "ǖ": "u", "ṳ": "u", "ụ": "u", "ű": "u", "ȕ": "u", "ù": "u", "ủ": "u", "ư": "u", "ứ": "u", "ự": "u", "ừ": "u", "ử": "u", "ữ": "u", "ȗ": "u", "ū": "u", "ṻ": "u", "ų": "u", "ᶙ": "u", "ů": "u", "ũ": "u", "ṹ": "u", "ṵ": "u", "ᵫ": "ue", "ꝸ": "um", "ⱴ": "v", "ꝟ": "v", "ṿ": "v", "ʋ": "v", "ᶌ": "v", "ⱱ": "v", "ṽ": "v", "ꝡ": "vy", "ẃ": "w", "ŵ": "w", "ẅ": "w", "ẇ": "w", "ẉ": "w", "ẁ": "w", "ⱳ": "w", "ẘ": "w", "ẍ": "x", "ẋ": "x", "ᶍ": "x", "ý": "y", "ŷ": "y", "ÿ": "y", "ẏ": "y", "ỵ": "y", "ỳ": "y", "ƴ": "y", "ỷ": "y", "ỿ": "y", "ȳ": "y", "ẙ": "y", "ɏ": "y", "ỹ": "y", "ź": "z", "ž": "z", "ẑ": "z", "ʑ": "z", "ⱬ": "z", "ż": "z", "ẓ": "z", "ȥ": "z", "ẕ": "z", "ᵶ": "z", "ᶎ": "z", "ʐ": "z", "ƶ": "z", "ɀ": "z", "ff": "ff", "ffi": "ffi", "ffl": "ffl", "fi": "fi", "fl": "fl", "ij": "ij", "œ": "oe", "st": "st", "ₐ": "a", "ₑ": "e", "ᵢ": "i", "ⱼ": "j", "ₒ": "o", "ᵣ": "r", "ᵤ": "u", "ᵥ": "v", "ₓ": "x" @@ -285,7 +267,36 @@ Response.prototype = { newBody += body[i]; } } - return this.add(new Speak(Response), newBody, attributes); + body = newBody; + + // If attributes not provided, use empty dictionary + if (!attributes) { + attributes = {}; + } + + // Validate voice first. + if (!attributes.voice) { + attributes.voice = 'WOMAN'; + } + if (!attributes.language) { + attributes.language = 'English'; + } + + var item = this; + plivoUtils.validateVoiceForSsml(body, attributes.voice, attributes.language).then((ssmlValidationResult) => { + console.log('validation result', ssmlValidationResult); + }); + + return item.add(new Speak(Response), body, attributes); + // plivoUtils.validateVoiceForSsml(body, attributes.voice, attributes.language).then(function (validationResult) { + // console.log('===> validation result', validationResult); + // if (!validationResult.success) { + // throw new Exceptions.PlivoXMLValidationError(validationResult.msg); + // return; + // } + // console.log('body is ', body); + // return item.add(new Speak(Response), body, attributes); + // }); }, diff --git a/package-lock.json b/package-lock.json index bfdb65a..125f1f4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "plivo", - "version": "4.0.5", + "version": "4.1.1", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -4669,6 +4669,11 @@ "integrity": "sha512-1HwIYD/8UlOtFS3QO3w7ey+SdSDFE4HRNLZoZRYVQefrOY3l17epswImeB1ijgJFQJodIaHcwkp3r/myBjFVbg==", "dev": true }, + "sax": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", + "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==" + }, "semver": { "version": "4.3.6", "resolved": "https://registry.npmjs.org/semver/-/semver-4.3.6.tgz", @@ -5565,6 +5570,15 @@ "mkdirp": "^0.5.1" } }, + "xml2js": { + "version": "0.4.19", + "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.19.tgz", + "integrity": "sha512-esZnJZJOiJR9wWKMyuvSE1y6Dq5LCuJanqhxslH2bxM6duahNZ+HMpCLhBQGZkbX6xRf8x1Y2eJlgt2q3qo49Q==", + "requires": { + "sax": ">=0.6.0", + "xmlbuilder": "~9.0.1" + } + }, "xmlbuilder": { "version": "9.0.7", "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-9.0.7.tgz", diff --git a/package.json b/package.json index 8b5ed49..dd415fd 100644 --- a/package.json +++ b/package.json @@ -64,6 +64,7 @@ "request": "^2.81.0", "uri-parser": "^1.0.0", "utf8": "^2.1.2", + "xml2js": "^0.4.19", "xmlbuilder": "^9.0.1" } -} \ No newline at end of file +} diff --git a/test/ssml.js b/test/ssml.js index 1dd37c1..b6368cd 100644 --- a/test/ssml.js +++ b/test/ssml.js @@ -5,8 +5,21 @@ import { PlivoGenericResponse } from '../lib/base.js'; let client = new Client('sampleid', 'sammpletoken', 'sampleproxy'); -let response = new Response(); -let speak_body = "Hello, world!"; -response.addSpeak(speak_body, { voice: 'SRD' }); -console.log(response.toXML()); +describe('SsmlInterface', function () { + it('test', function () { + let response = new Response(); + let speak_body = ' Here is a number read \ + as a cardinal number: \ + 12345. \ + Here is a word spelled out: \ + hello.'; + + // response.addSpeak(speak_body, { language: 'Spanish-Castilian', voice: 'Polly.Conchita' }); + response.addSpeak(speak_body, { language: 'Spanish-Castilian', voice: 'Polly.Conchita' }); + console.log(response.toXML()); + + + + }); +});