UNPKG

@ibgib/helper-gib

Version:

common helper/utils/etc used in ibgib libs. Node v19+ needed for heavily-used isomorphic webcrypto hashing consumed in both node and browsers.

1,050 lines (1,049 loc) 32.1 kB
import { HELPER_LOG_A_LOT } from "../constants.mjs"; const logalot = HELPER_LOG_A_LOT || true; /** * Values that indicate how Alexa should speak text. * To be used with Ssml.sayAs({text, interpret: As.characters}) */ export const As = { /** * Spell out each letter. */ characters: "characters", /** * Spell out each letter. */ spell_out: "spell-out", /** * Interpret the value as a cardinal number. * * @example "12" is pronounced as "twelve" and not "1-2". */ cardinal: "cardinal", /** * Interpret the value as a cardinal number. * * @example "12" is pronounced as "twelve" and not "1-2". */ number: "number", /** * Interpret the value as an ordinal number. * * @example "12" is pronounced as "twelfth" */ ordinal: "ordinal", /** * Spell each digit separately. */ digits: "digits", /** * Interpret the value as a fraction. This works for both common * fractions (such as 3/20) and mixed fractions (such as 1+1/2). */ fraction: "fraction", /** * Interpret a value as a measurement. The value should be either a * number or fraction followed by a unit (with no space in between) * or just a unit. */ unit: "unit", /** * Interpret the value as a date. Specify the format with the * format attribute. */ date: "date", /** * Interpret a value such as 1'21" as duration in minutes and * seconds. */ time: "time", /** * Interpret a value as a 7-digit or 10-digit telephone number. * This can also handle extensions (for example, 2025551212x345). */ telephone: "telephone", /** * Interpret a value as part of street address. */ address: "address", /** * askGib NOTE: SpeechCons are already implemented directly: e.g. `Ssml.speech(Con.abracadabra)` * * Interpret the value as an interjection. Alexa speaks the text in * a more expressive voice. For optimal results, only use the * supported interjections and surround each one with a pause. For * * @example * <say-as interpret-as="interjection">Wow.</say-as>. * * Speechcons are supported for English (US), English (UK), and * German. */ interjection: "interjection", /** * “Bleep” out the content inside the tag. */ expletive: "expletive", }; /** * Date formats, used with @see {sayAs} function when * @see {InterpretAs} is "date". * * Alternatively, if you provide the date in YYYYMMDD format, the * format attribute is ignored. You can include question marks (?) for * portions of the date to leave out. For instance, Alexa would speak * <say-as interpret-as="date">????0922</say-as> as “September 22nd”. */ export const SayAsDate = { mdy: "mdy", dmy: "dmy", ymd: "ymd", md: "md", dm: "dm", ym: "ym", my: "my", d: "d", m: "m", y: "y", }; /** * Special interjections that Alexa can say. * I have this called only "Con" for readability of calling code. * * https://developer.amazon.com/public/solutions/alexa/alexa-skills-kit/docs/speechcon-reference * * All spaces in keys are replaced with underscores. */ export const Con = { abracadabra: "abracadabra", achoo: "achoo", aha: "aha", ahem: "ahem", ahoy: "ahoy", all_righty: "all righty", aloha: "aloha", aooga: "aooga", argh: "argh", arrivederci: "arrivederci", as_you_wish: "as you wish", attagirl: "attagirl", au_revoir: "au revoir", avast_ye: "avast ye", aw_man: "aw man", baa: "baa", bada_bing_bada_boom: "bada bing bada boom", bah_humbug: "bah humbug", bam: "bam", bang: "bang", batter_up: "batter up", bazinga: "bazinga", beep_beep: "beep beep", bingo: "bingo", blah: "blah", blarg: "blarg", blast: "blast", boing: "boing", bon_appetit: "bon appetit", bonjour: "bonjour", bon_voyage: "bon voyage", boo: "boo", boo_hoo: "boo hoo", boom: "boom", booya: "booya", bravo: "bravo", bummer: "bummer", caw: "caw", cha_ching: "cha ching", checkmate: "checkmate", cheerio: "cheerio", cheers: "cheers", cheer_up: "cheer up", chirp: "chirp", choo_choo: "choo choo", clank: "clank", click_clack: "click clack", cock_a_doodle_doo: "cock a doodle doo", coo: "coo", cowabunga: "cowabunga", darn: "darn", ding_dong: "ding dong", ditto: "ditto", doh: "doh", dot_dot_dot: "dot dot dot", duh: "duh", dum: "dum", dun_dun_dun: "dun dun dun", dynomite: "dynomite", eek: "eek", eep: "eep", encore: "encore", en_gard: "en gard", eureka: "eureka", fancy_that: "fancy that", geronimo: "geronimo", giddy_up: "giddy up", good_grief: "good grief", good_luck: "good luck", good_riddance: "good riddance", gotcha: "gotcha", great_scott: "great scott", heads_up: "heads up", hear_hear: "hear hear", hip_hip_hooray: "hip hip hooray", hiss: "hiss", honk: "honk", howdy: "howdy", hurrah: "hurrah", hurray: "hurray", huzzah: "huzzah", jeepers_creepers: "jeepers creepers", jiminy_cricket: "jiminy cricket", jinx: "jinx", just_kidding: "just kidding", kaboom: "kaboom", kablam: "kablam", kaching: "kaching", kapow: "kapow", katchow: "katchow", kazaam: "kazaam", kerbam: "kerbam", kerboom: "kerboom", kerching: "kerching", kerchoo: "kerchoo", kerflop: "kerflop", kerplop: "kerplop", kerplunk: "kerplunk", kerpow: "kerpow", kersplat: "kersplat", kerthump: "kerthump", knock_knock: "knock knock", le_sigh: "le sigh", look_out: "look out", mamma_mia: "mamma mia", man_overboard: "man overboard", mazel_tov: "mazel tov", meow: "meow", merci: "merci", moo: "moo", nanu_nanu: "nanu nanu", neener_neener: "neener neener", no_way: "no way", now_now: "now now", oh_boy: "oh boy", oh_brother: "oh brother", oh_dear: "oh dear", oh_my: "oh my", oh_snap: "oh snap", oink: "oink", okey_dokey: "okey dokey", oof: "oof", ooh_la_la: "ooh la la", open_sesame: "open sesame", ouch: "ouch", oy: "oy", phew: "phew", phooey: "phooey", ping: "ping", plop: "plop", poof: "poof", pop: "pop", pow: "pow", quack: "quack", read_em_and_weep: "read em and weep", ribbit: "ribbit", righto: "righto", roger: "roger", ruh_roh: "ruh roh", shucks: "shucks", splash: "splash", spoiler_alert: "spoiler alert", squee: "squee", swish: "swish", swoosh: "swoosh", ta_da: "ta da", ta_ta: "ta ta", tee_hee: "tee hee", there_there: "there there", thump: "thump", tick_tick_tick: "tick tick tick", tick_tock: "tick tock", touche: "touche", tsk_tsk: "tsk tsk", tweet: "tweet", uh_huh: "uh huh", uh_oh: "uh oh", um: "um", voila: "voila", vroom: "vroom", wahoo: "wahoo", wah_wah: "wah wah", watch_out: "watch out", way_to_go: "way to go", well_done: "well done", well_well: "well well", wham: "wham", whammo: "whammo", whee: "whee", whew: "whew", woof: "woof", whoops_a_daisy: "whoops a daisy", whoosh: "whoosh", woo_hoo: "woo hoo", wow: "wow", wowza: "wowza", wowzer: "wowzer", yadda_yadda_yadda: "yadda yadda yadda", yay: "yay", yikes: "yikes", yippee: "yippee", yoink: "yoink", yoo_hoo: "yoo hoo", you_bet: "you bet", yowza: "yowza", yowzer: "yowzer", yuck: "yuck", yum: "yum", zap: "zap", zing: "zing", zoinks: "zoinks", }; export const ConUK = { abracadabra: "abracadabra", ace: "ace", achoo: "achoo", ahoy: "ahoy", all: "all", aloha: "aloha", aooga: "aooga", arrivederci: "arrivederci", as_if: "as if", as_you_wish: "as you wish", au_revoir: "au revoir", aw: "aw", aw_man: "aw man", awesome: "awesome", baa: "baa", bah_humbug: "bah humbug", bam: "bam", bang: "bang", bazinga: "bazinga", beep_beep: "beep beep", bingo: "bingo", blah: "blah", blarg: "blarg", blast: "blast", blimey: "blimey", bobs_your_uncle: "bobs your uncle", boing: "boing", bon_appetit: "bon appetit", bon_voyage: "bon voyage", bonjour: "bonjour", boo: "boo", boo_hoo: "boo hoo", booya: "booya", bother: "bother", bravo: "bravo", caw: "caw", cha_ching: "cha ching", checkmate: "checkmate", cheer_up: "cheer up", cheerio: "cheerio", cheers: "cheers", chirp: "chirp", choo_choo: "choo choo", clank: "clank", clickety_clack: "clickety clack", cock_a_doodle_doo: "cock a doodle doo", codswallop: "codswallop", coo: "coo", cowabunga: "cowabunga", crikey: "crikey", doh: "doh", darn: "darn", ditto: "ditto", dot_dot_dot: "dot dot dot", duh: "duh", dun_dun_dun: "dun dun dun", eek: "eek", eep: "eep", en_garde: "en garde", encore: "encore", eureka: "eureka", ew: "ew", fancy_that: "fancy that", geronimo: "geronimo", giddy_up: "giddy up", good_golly: "good golly", good_grief: "good grief", good_luck: "good luck", good_riddance: "good riddance", gosh: "gosh", gotcha: "gotcha", great_scott: "great scott", ha: "ha", ha_ha: "ha ha", heads_up: "heads up", hear_hear: "hear hear", hip_hip_hooray: "hip hip hooray", hiss: "hiss", honk: "honk", howdy: "howdy", howzat: "howzat", hurrah: "hurrah", hurray: "hurray", huzzah: "huzzah", jeepers_creepers: "jeepers creepers", jiminy_cricket: "jiminy cricket", jinx: "jinx", just_kidding: "just kidding", kablam: "kablam", kaboom: "kaboom", kaching: "kaching", kapow: "kapow", knock_knock: "knock knock", le_sigh: "le sigh", look_out: "look out", mamma_mia: "mamma mia", man_overboard: "man overboard", mazel_tov: "mazel tov", meow: "meow", merci: "merci", moo: "moo", no_way: "no way", nom_nom: "nom nom", now_now: "now now", oh_boy: "oh boy", oh_dear: "oh dear", oh_my: "oh my", oh_my_giddy_aunt: "oh my giddy aunt", oh_snap: "oh snap", okey_dokey: "okey dokey", oof: "oof", ooh_la_la: "ooh la la", open_sesame: "open sesame", ouch: "ouch", ow: "ow", oy: "oy", pardon: "pardon", phew: "phew", phooey: "phooey", ping: "ping", plop: "plop", pop: "pop", pow: "pow", quack: "quack", read_em_and_weep: "read em and weep", ribbit: "ribbit", righto: "righto", roger: "roger", sigh: "sigh", simples: "simples", splash: "splash", spoiler_alert: "spoiler alert", squee: "squee", swish: "swish", swoosh: "swoosh", ta_da: "ta da", tallyho: "tallyho", tee_hee: "tee hee", there_there: "there there", thump: "thump", tick_tick_tick: "tick tick tick", tick_tock: "tick tock", tosh: "tosh", touche: "touche", tsk_tsk: "tsk tsk", tut_tut: "tut tut", tweet: "tweet", uh_huh: "uh huh", uh_oh: "uh oh", voila: "voila", vroom: "vroom", wahoo: "wahoo", watch_out: "watch out", way_to_go: "way to go", well_done: "well done", well_well: "well well", wham: "wham", whammo: "whammo", whee: "whee", whoop: "whoop", whoops: "whoops", whoops_a_daisy: "whoops a daisy", whoosh: "whoosh", woo_hoo: "woo hoo", wow: "wow", wowza: "wowza", yadda_yadda_yadda: "yadda yadda yadda", yippee: "yippee", yoink: "yoink", you_bet: "you bet", yowza: "yowza", yum: "yum", zap: "zap", zing: "zing", zoinks: "zoinks", }; export const ConDE = { aber_hallo: "aber hallo", aber_sicher: "aber sicher", abrakadabra: "abrakadabra", ach: "ach", ach_du_grüne_neune: "ach du grüne neune", ach_du_liebe_zeit: "ach du liebe zeit", ach_du_meine_güte: "ach du meine güte", ach_ja: "ach ja", ach_so: "ach so", achje: "achje", achtung: "achtung", ade: "ade", ah: "ah", aha: "aha", ähm: "ähm", ahoi: "ahoi", alles_klar: "alles klar", aloha: "aloha", als_ob: "als ob", argh: "argh", arrivederci: "arrivederci", aso: "aso", au: "au", au_weia: "au weia", aua: "aua", autsch: "autsch", bazinga: "bazinga", bingo: "bingo", bis_bald: "bis bald", bis_dann: "bis dann", bla: "bla", boing: "boing", bon_appetit: "bon appetit", bon_voyage: "bon voyage", bonjour: "bonjour", bravo: "bravo", brumm: "brumm", buh: "buh", buhu: "buhu", bumm: "bumm", bzz: "bzz", da_lachen_ja_die_hühner: "da lachen ja die hühner", ding_dong: "ding dong", dito: "dito", donner_und_doria: "donner und doria", donnerwetter: "donnerwetter", ebenso: "ebenso", en_garde: "en garde", ey: "ey", geh_nur: "geh nur", gemach: "gemach", genug: "genug", gesundheit: "gesundheit", gott_im_himmel: "gott im himmel", grüß_gott: "grüß gott", gute_reise: "gute reise", guten_appetit: "guten appetit", hach_ja: "hach ja", halleluja: "halleluja", hals_und_beinbruch: "hals und beinbruch", halt: "halt", hände_hoch: "hände hoch", heiliger_strohsack: "heiliger strohsack", heisa: "heisa", hey: "hey", hihi: "hihi", hipp_hipp_hurra: "hipp hipp hurra", hört_hört: "hört hört", hü: "hü", hüa: "hüa", huch: "huch", huhu: "huhu", hui: "hui", hurra: "hurra", ich_glaub_ich_bin_im_kino: "ich glaub ich bin im kino", ich_glaub_mein_schwein_pfeift: "ich glaub mein schwein pfeift", ich_glaub_mich_knutscht_ein_elch: "ich glaub mich knutscht ein elch", ich_glaub_mich_laust_der_affe: "ich glaub mich laust der affe", ich_glaub_mich_tritt_ein_pferd: "ich glaub mich tritt ein pferd", igitt: "igitt", iiieh: "iiieh", ist_nicht_dein_ernst: "ist nicht dein ernst", japp: "japp", jawohl: "jawohl", jo: "jo", juhu: "juhu", kein_kommentar: "kein kommentar", keine_ursache: "keine ursache", kikeriki: "kikeriki", klar: "klar", klick_klack: "klick klack", kopf_hoch: "kopf hoch", kuckuck: "kuckuck", lass_es_dir_schmecken: "lass es dir schmecken", lecker: "lecker", los: "los", mach: "mach's gut", mahlzeit: "mahlzeit", mamma_mia: "mamma mia", mann_über_bord: "mann über bord", manometer: "manometer", mazel_tov: "mazel tov", mein_gott: "mein gott", merci: "merci", miau: "miau", mist: "mist", moin: "moin", muh: "muh", na_klar: "na klar", na_sieh_mal_einer_an: "na sieh mal einer an", na_und_: "na und?", na_: "na?", naja: "naja", nanu: "nanu", ne: "ne", nee: "nee", nichts_da: "nichts da", nix_da: "nix da", nö: "nö", null_problemo: "null problemo", obacht: "obacht", och: "och", oh_mann: "oh mann", oh_mein_gott: "oh mein gott", oh_my_god: "oh my god", oh_nein: "oh nein", oh_oh: "oh oh", ohne_scheiß: "ohne scheiß", oink: "oink", oje: "oje", okey_dokey: "okey dokey", ooh_la_la: "ooh la la", pfui: "pfui", piep: "piep", plop: "plop", plumps: "plumps", prima: "prima", prosit: "prosit", prost: "prost", puff: "puff", puh: "puh", pustekuchen: "pustekuchen", schachmatt: "schachmatt", schade: "schade", schau_an: "schau an", sesam_öffne_dich: "sesam öffne dich", seufz: "seufz", sieh_an: "sieh an", siehe_da: "siehe da", siehste: "siehste", spoileralarm: "spoileralarm", stimmt: "stimmt", super: "super", supi: "supi", süßes_oder_saures: "süßes oder saures", tada: "tada", tatsächlich: "tatsächlich", tick_tack: "tick tack", tja: "tja", touche: "touche", tschö: "tschö", türlich: "türlich", tut: "tut", uff: "uff", verdammt: "verdammt", verflixt: "verflixt", viel_glück: "viel glück", voila: "voila", von_wegen: "von wegen", vorsicht: "vorsicht", war_nur_ein_scherz: "war nur ein scherz", was_zur_hölle: "was zur hölle", weh_mir: "weh mir", wehe: "wehe", wie_du_meinst: "wie du meinst", willkommen: "willkommen", wow: "wow", wuff: "wuff", yay: "yay", zugabe: "zugabe", zum_wohl: "zum wohl", }; export const Effect = { whispered: "whispered", }; export const PartOfSpeech = { /** * Interpret the word as a verb (present simple). */ verb: "amazon:VB", /** * Interpret the word as a past participle. */ past_participle: "amazon:VBD", /** * Interpret the word as a noun. */ noun: "amazon:NN", /** * Use the non-default sense of the word. For example, * the noun “bass” is pronounced differently depending on meaning. * The “default” meaning is the lowest part of the musical range. * The alternate sense (which is still a noun) is a freshwater * fish. Specifying * <speak><w role="amazon:SENSE_1">bass</w>"</speak> * renders the non-default pronunciation (freshwater fish). */ sense1: "amazon:SENSE_1", }; export class Ssml { /** * Wraps a given list of paragraph strings in `<speak>` tags, with * optional paragraph `<p>` tags. * * @param paras individual paragraphs to be wrapped in <p></p> tags. * @param addParaTags If true, wraps individual strings in paras with `<p>` tags. Otherwise just concats. */ static wrapSsmlSpeak(paras, addParaTags = true) { let result = "<speak>" + paras.reduce((agg, p) => { return addParaTags ? agg + "<p>" + p + "</p>" : agg + p; }, "") + "</speak>"; return result; } /** * This simply replaces <speak> and </speak> tags with an empty * string. * * Use this when you want to add some text to existing ssml and * then re-wrap the ssml. * * @see {Helper.stripSsml} function. * * @param ssml with <speak> tag around the whole thing. */ static unwrapSsmlSpeak(ssml) { return ssml.replace(/\<speak\>/g, "").replace(/\<\/speak\>/g, ""); } /** * Simply wraps with <p> tag. * * Represents a paragraph. This tag provides extra-strong breaks * before and after the tag. This is equivalent to specifying a * pause with <break strength="x-strong"/>. * * @param text to wrap */ static p(text) { return '<p>' + text + '</p>'; } /** * Simply wraps with <s> tag. * * Represents a sentence. This tag provides strong breaks before * and after the tag. * * This is equivalent to: * Ending a sentence with a period (.). * Specifying a pause with <break strength="strong"/>. * @param text to wrap */ static s(text) { return '<s>' + text + '</s>'; } /** * Strips all tags within ssml to produce plain text. * * @see {Helper.unwrapSsmlSpeak} function. * * @param ssml to strip */ static stripSsml(ssml) { const stripped = ssml // Combines </p> <p> to not double para breaks .replace(/\<\/p\>[ ]*\<p\>/g, "<p>") // remove spaces after <p>,</p> tags .replace(/\<p\>(?=[ ])/g, "<p>") .replace(/\<\/p\>(?=[ ])/g, "</p>") // convert <p> and </p> to two new lines .replace(/\<[\/]*p\>/g, "\n\n") // Strip all remaining tags .replace(/(<([^>]*)>)/ig, "") // Replace multiple spaces with a single space .replace(/ +/g, ' ') .replace(/\\n\\n\\n/g, "\n\n") // .replace(/^\\n+/, "") .replace(/^\n+/, "") .replace(/\n+$/, ""); return stripped; } /** * Wraps a given text in an ssml phoneme tag with the given * pronunciation and alphabet. * * @param text Literal text that we're wrapping the phoneme tag around, e.g. "sewing". * @param pronunciation the phoneme itself, e.g. "soʊɪŋ" * @param alphabet phoneme alphabet, either "ipa" or "x-sampe" (ATOW) * * @see {@link https://developer.amazon.com/public/solutions/alexa/alexa-skills-kit/docs/speech-synthesis-markup-language-ssml-reference#prosody|SsmlReference} */ static phoneme(text, pronunciation, alphabet = "ipa") { return `<phoneme alphabet="${alphabet}" ph="${pronunciation}">${text}</phoneme>`; } /** * Wraps a given text in an ssml emphasis tag. * * e.g. <emphasis level="${level}">${text}</emphasis>` * * @param text to wrap with the emphasis tag * @param level attribute in emphasis tag. Valid values "strong" | "moderate" | "reduced" = "moderate" * * @see {@link https://developer.amazon.com/public/solutions/alexa/alexa-skills-kit/docs/speech-synthesis-markup-language-ssml-reference#prosody|SsmlReference} */ static emphasis(text, level = "moderate") { return `<emphasis level="${level}">${text}</emphasis>`; } /** * Wraps a given text in an ssml prosody tag with the given * options of rate, pitch, and/or volume. * * @param rate valid values ATOW "x-slow" | "slow" | "medium" | "fast" | "x-fast" | number, * @param pitch valid values ATOW "x-low" | "low" | "medium" | "high" | "x-high" | number, * @param volume valid values ATOW "silent" | "x-soft" | "soft" | "medium" | "loud" | "x-loud" | number * * @see {@link https://developer.amazon.com/public/solutions/alexa/alexa-skills-kit/docs/speech-synthesis-markup-language-ssml-reference#prosody|SsmlReference} */ // static prosody(text, { rate, pitch, volume }) { static prosody(text, { rate, pitch, volume }) { const lc = `${Ssml.lc}${Ssml.prosody.name}`; let attrs = ""; // adds the + to positive numbers if (rate || rate === 0) { const rateText = typeof rate === 'number' ? rate + "%" : rate; attrs += `rate="${rateText}"`; } if (pitch || pitch === 0) { let pitchText; if (typeof pitch === 'number') { const pitchNum = pitch; if (pitch >= 0) { const max = 50; if (pitchNum > max) { console.warn(`${lc} max: ${max}, actual: ${pitchNum} (W: 7fd9706e59f24dba896e2de149904677)`); } pitchText = "+" + pitchNum + "%"; } else { const min = -33.3; if (pitchNum < min) { console.warn(`${lc} min: ${min}, actual: ${pitchNum} (W: 90f4c21672034c51a8a95dcfcd281f98)`); } pitchText = "-" + pitchNum + "%"; } } else { pitchText = pitch; } attrs = attrs ? attrs + " " : attrs; attrs += `pitch="${pitchText}"`; } if (volume || volume === 0) { let volumeText; if (typeof volume === 'number') { let volumeNum = volume; if (volumeNum >= 0) { const max = 4.08; if (volumeNum > max) { console.warn(`${lc} max: ${max}, actual: ${volumeNum} (W: 7db9521e6b3e418faca89d2f5cfa4f2c)`); } volumeText = "+" + volumeNum + "%"; } else { const min = -12; if (volumeNum < min) { console.warn(`${lc} min: ${min}, actual: ${volumeNum} (W: 49210d930272498e828d2c9a815ceea0)`); } } volumeText = volumeNum + "%"; } else { volumeText = volume; } attrs = attrs ? attrs + " " : attrs; attrs += (volume ? `volume="${volumeText}"` : ""); } return "<prosody " + attrs + ">" + text + "</prosody>"; } /** * Generates SpeechCon SSML. * https://developer.amazon.com/public/solutions/alexa/alexa-skills-kit/docs/speechcon-reference */ static speech(speechCon) { return `<say-as interpret-as="interjection">${speechCon}</say-as>`; } /** * Applies Amazon-specific effects to the speech. * * https://developer.amazon.com/public/solutions/alexa/alexa-skills-kit/docs/speech-synthesis-markup-language-ssml-reference#amazon-effect * * The name of the effect to apply to the speech. Available effects: * whispered: Applies a whispering effect to the speech. * @param effect Which amazon:effect. ATOW only whispered implemented. * @param s text to wrap in the effect. */ static amazon(effect, s) { return `<amazon:effect name="${effect}">${s}</amazon:effect>`; } /** * The audio tag lets you provide the URL for an MP3 file that the * Alexa service can play while rendering a response. You can use * this to embed short, pre-recorded audio within your service’s * response. For example, you could include sound effects alongside * your text-to-speech responses, or provide responses using a * voice associated with your brand. For more information, see * Including Short Pre-Recorded Audio in your Response at * https://developer.amazon.com/public/solutions/alexa/alexa-skills-kit/docs/handling-requests-sent-by-alexa#audio. * * Note the following requirements and limitations: * * * The MP3 must be hosted at an Internet-accessible HTTPS * endpoint. HTTPS is required, and the domain hosting the MP3 * file must present a valid, trusted SSL certificate. * Self-signed certificates cannot be used. * * The MP3 must not contain any customer-specific or other * sensitive information. * * The MP3 must be a valid MP3 file (MPEG version 2). * * The audio file cannot be longer than ninety (90) seconds. * * The bit rate must be 48 kbps. Note that this bit rate gives a * good result when used with spoken content, but is generally * not a high enough quality for music. * * The sample rate must be 16000 Hz. * * You may need to use converter software to convert your MP3 files * to the required codec version (MPEG version 2) and bit rate (48 * kbps). * * https://developer.amazon.com/public/solutions/alexa/alexa-skills-kit/docs/speech-synthesis-markup-language-ssml-reference#audio * * @param srcUrl Specifies the URL for the MP3 file. */ static audio(srcUrl) { return `<audio src="${srcUrl}" />`; } /** * Represents a pause in the speech. Set the length of the pause * with the strength or time attributes. * * https://developer.amazon.com/public/solutions/alexa/alexa-skills-kit/docs/speech-synthesis-markup-language-ssml-reference#break * * @param param0 */ static break({ strength, s, ms }) { const lc = `${Ssml.lc}${Ssml.break.name}`; if (strength) { return `<break strength="${strength}"/>`; } else if (s || s === 0) { const min = 0; const max = 10; if (s < min) { console.warn(`${lc} min: ${min}, actual: ${s} (W: 6ff97060a6734f20b16a81a20d06630e)`); s = min; } else if (s > max) { console.warn(`${lc} max: ${max}, actual: ${s} (W: d57ed120e09c4fcaa19b864bdf9f1fc7)`); s = max; } return `<break time="${s}s"/>`; } else if (ms || ms === 0) { const min = 0; const max = 10000; if (ms < min) { console.warn(`min: ${min}, actual: ${ms} (W: 0addf6dbab1844a9906bd18a859be3d7)`); ms = 0; } else if (ms > max) { console.warn(`max: ${max}, actual: ${ms} (W: f46b9868ec6d4ef2abd4f2aefe879427)`); ms = max; } return `<break time="${ms}ms"/>`; } else { throw new Error('Unknown break parameters (E: 1ae569301a354c28a54cc06b58c93b87)'); } } /** * Takes a given text that will be written and provides an alias * for it when it's actually spoken. * * For example, if the written text is the element symbol "Mg", then * you probably want to verbally say the entire word: "Magnesium". * In this case, the "text" is "Mg" and the "alias" is "Magnesium". * * @see (@link https://developer.amazon.com/public/solutions/alexa/alexa-skills-kit/docs/speech-synthesis-markup-language-ssml-reference#sub) * * @param text Written text that will be substituted when spoken, e.g. "Mg" * @param alias Spoken alias that will be spoken, e.g. "Magnesium" */ static sub(text, alias) { return `<sub alias="${alias}">${text}</sub>`; } /** * Similar to <say-as>, this tag customizes the pronunciation of * words by specifying the word’s part of speech. * * @param text Text that requires clarity. * @param partOfSpeech Context provided for the given text. */ static w(text, partOfSpeech) { return `<w role="${partOfSpeech}">${text}</w>`; } /** * Describes how the text should be interpreted. This lets you * provide additional context to the text and eliminate any * ambiguity on how Alexa should render the text. Indicate how * Alexa should interpret the text with the interpret-as attribute. * * Note that the Alexa service attempts to interpret the provided * text correctly based on the text’s formatting even without this * tag. For example, if your output speech includes “202-555-1212”, * Alexa speaks each individual digit, with a brief pause for each * dash. You don’t need to use <say-as interpret-as="telephone"> in * this case. However, if you provided the text “2025551212”, but * you wanted Alexa to speak it as a phone number, you would need * to use <say-as interpret-as="telephone">. * * @example * <speak> * Here is a number spoken as a cardinal number: * <say-as interpret-as="cardinal">12345</say-as>. * Here is the same number with each digit spoken separately: * <say-as interpret-as="digits">12345</say-as>. * Here is a word spelled out: <say-as interpret-as="spell-out">hello</say-as> * </speak> * * @see * https://developer.amazon.com/public/solutions/alexa/alexa-skills-kit/docs/speech-synthesis-markup-language-ssml-reference#say-as */ static sayAs({ text, interpret, format }) { const lc = `${Ssml.lc}[${Ssml.sayAs.name}]`; try { if (format) { if (interpret !== As.date) { throw new Error(`\`format\` arg requires (implies) \`interpret\` === "date" (E: 2a470b25ac284ec4bec9eb3e6a704b6b)`); } return `<say-as interpret-as="${interpret}" format="${format}">${text}</say-as>`; } else { return `<say-as interpret-as="${interpret}">${text}</say-as>`; } } catch (error) { console.error(`${lc} ${error.message}`); throw error; } } } Ssml.lc = `[${Ssml.name}]`; //# sourceMappingURL=ssml-helper.mjs.map