/******************************************************************************
*
* Copyright 2014-2023 Paphus Solutions Inc.
*
* Licensed under the Eclipse Public License, Version 1.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.eclipse.org/legal/epl-v10.html
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
******************************************************************************/
/**
* Bot Libre open SDK.
* This JavaScript SDK lets you access chat bot, live chat, chatroom, forum, script, graphic, user services on
* the Bot Libre compatible websites, including:
* - Bot Libre
* - Bot Libre for Business
* - Bot Libre Community Edition
* - Bot Libre Enterprise
*
* This JavaScript script can be used directly, or copied/modified on your own website.
*
* The SDK consist of two main class, SDKConnection and LiveChatConnection.
*
* SDKConnection uses AJAX calls to provide access to the Bot Libre REST API.
* This is used for chat bots, live chat, chatrooms, forums, issue tracking, user admin, and workspaces.
*
* LiveChatConnection uses web sockets to provide access to live chat and chatrooms.
*
* Version: 9.5.0-2023-05-04
*/
/**
* Static class for common util functions and static properties.
* @class
*/
var SDK = {};
// Production server
SDK.DOMAIN = "www.botlibre.com";
SDK.NAME = "Bot Libre";
SDK.APP = "";
SDK.scheme = "https";
// Development server (comment for production or uncomment development)
//SDK.DOMAIN = window.location.host;
//SDK.DOMAIN = "144.217.65.190";
//SDK.APP = "/botlibre";
//SDK.scheme = "https:" == document.location.protocol ? "https" : "http";
SDK.PATH = "/rest/api";
SDK.MAX_FILE_UPLOAD = 5000000;
SDK.host = SDK.DOMAIN;
SDK.app = SDK.APP;
SDK.url = SDK.scheme + "://" + SDK.DOMAIN + SDK.APP;
SDK.rest = SDK.url + SDK.PATH;
SDK.backlinkURL = SDK.url;
SDK.backlink = true;
SDK.commands = true;
SDK.turnServer = null;
SDK.turnUser = null;
SDK.turnPassword = null;
/**
* You must set your application ID to use the SDK.
* You can obtain your application ID from your user page.
* @static
*/
SDK.applicationId = null;
/**
* Set the active language code.
* This is used for voice recognition.
*/
SDK.lang = "en";
/**
* Enable debug logging.
* @static
*/
SDK.debug = false;
/**
* Escape and filter bot messages for HTML and JavaScript content for XSS security.
* This prevents bots sending advanced HTML and JavaScript in their messages.
* Set this to false to allow your bot to send JavaScript.
* @static
*/
SDK.secure = true;
/**
* Force avatars to enable or disable canvas for video (currently used only for Chrome and Firefox).
* @static
*/
SDK.useCanvas = null;
/**
* Force avatars to enable or disable video (currently disabled for Safari on iPhone).
* @static
*/
SDK.useVideo = null;
/**
* Set the background for video avatars.
* @static
*/
SDK.videoBackground = true;
/**
* Attempt to fix grey mp4 video background (only used for Chrome).
* @static
*/
SDK.fixBrightness = null;
/**
* Attempt to fix an issue with Chrome not processing the CSS after correctly when the chat bubble resizes.
* @static
*/
SDK.fixChromeResizeCSS = false;
// Polyfill IE
if (!String.prototype.includes) {
String.prototype.includes = function(search, start) {
if (typeof start !== 'number') {
start = 0;
}
if (start + search.length > this.length) {
return false;
} else {
return this.indexOf(search, start) !== -1;
}
};
}
/**
* Set the error static field to trap or log any errors.
*/
SDK.error = function(message) {
console.log(message);
}
/**
* Allow our native speech API to use the third party ResponsiveVoice API.
* You must create an account with ResponsiveVoice to use their API, see https://responsivevoice.com
* @static
*/
SDK.responsiveVoice = false;
SDK.speechSynthesis = 'speechSynthesis' in window;
/**
* The speechRate can be set to change the native speech voice speed.
* It can range between 0.1 (lowest) and 10.0 (highest).
* 1.0 is the default rate for the current platform or voice.
* Other values act as a percentage relative to this, so for example 2.0 is twice as fast, 0.5 is half as fast.
*/
SDK.speechRate = null;
/**
* The speechPitch can be set to change the native speech voice pitch.
* It can range between 0.0 (lowest) and 2.0 (highest), with 1.0 being the default pitch for the current platform or voice.
*/
SDK.speechRate = null;
SDK.initResponsiveVoice = function() {
if (!('responsiveVoice' in window)) {
console.log("ResponsiveVoice missing, you must load its script first");
return;
}
SDK.responsiveVoice = true;
SDK.speechSynthesis = true;
}
if (!('SpeechSynthesisUtterance' in window)) {
function SpeechSynthesisUtterance2(text) {
this.text = text;
}
}
/**
* Allow our native speech API to use the third party QQ Speech API.
*
* @static
*/
SDK.qqSpeech = false;
SDK.initQQSpeech = function(instanceId, type) {
SDK.qqSpeech = true;
SDK.speechSynthesis = true;
SDK.speechInstance = instanceId;
SDK.speechType = type;
console.log("Initializing QQ speech.");
}
/**
* Allow our native speech API to use the third party Google Speech API.
*
* @static
*/
SDK.googleSpeech = false;
SDK.initGoogleSpeech = function(instanceId, type) {
SDK.googleSpeech = true;
console.log("Initializing Google speech.");
}
/**
* Allow our native speech API to use the third party Microsoft Speech API.
*
* @static
*/
SDK.bingSpeech = false;
SDK.initBingSpeech = function(instanceId, type) {
SDK.bingSpeech = true;
console.log("Initializing Bing speech.");
}
SDK.currentAudio = null;
SDK.recognition = null;
SDK.recognitionActive = false;
SDK.backgroundAudio = null;
SDK.currentBackgroundAudio = null;
SDK.timers = {};
/**
* Track if auto play of media is enabled in the browser (mobile Chrome/Safari)
* Enable or disable to force audio auto play.
*/
SDK.canPlayAudio = null;
/**
* Track if auto play of media is enabled in the browser (mobile Chrome/Safari)
* Enable or disable to force video auto play.
*/
SDK.canPlayVideo = null;
SDK.disableAudioAutoPlay = false;
SDK.audio = null;
SDK.autoPlayActionAudio = null;
SDK.autoPlayBackgroundAudio = null;
SDK.autoPlayDelay = 2000;
/**
* For some browsers audio must be initialized from a click event.
*/
SDK.initAudio = function() {
SDK.canPlayVideo = true;
SDK.canPlayAudio = true;
if (SDK.audio == null) {
SDK.audio = new Audio(SDK.url + '/chime.mp3');
SDK.audio.load();
}
if (SDK.autoPlayActionAudio == null) {
SDK.autoPlayActionAudio = new Audio(SDK.url + '/chime.mp3');
SDK.autoPlayActionAudio.load();
SDK.autoPlayBackgroundAudio = new Audio(SDK.url + '/chime.mp3');
SDK.autoPlayBackgroundAudio.load();
}
}
/**
* Play the audio file given the url.
*/
SDK.play = function(file, channelaudio, baseRoot) {
SDK.pauseSpeechRecognition();
var audio = null;
if (SDK.audio != null) {
audio = SDK.audio;
audio.pause();
audio.onended = null;
audio.onpause = null;
audio.oncanplay = null;
audio.src = file;
} else {
audio = new Audio(file);
}
if (SDK.recognitionActive) {
audio.onended = function() {
SDK.startSpeechRecognition();
if (channelaudio != false) {
SDK.currentAudio = null;
}
};
} else if (channelaudio != false) {
audio.onended = function() {
SDK.currentAudio = null;
};
}
var playPromise = null;
if (channelaudio == false) {
playPromise = audio.play();
} else {
if (SDK.currentAudio != null && !SDK.currentAudio.ended && !SDK.currentAudio.paused) {
SDK.currentAudio.onpause = function() {
SDK.currentAudio = audio;
playPromise = audio.play();
};
SDK.currentAudio.pause();
} else {
SDK.currentAudio = audio;
playPromise = audio.play();
}
}
if (playPromise !== undefined && SDK.canPlayAudio == null) {
playPromise.then(function() {
SDK.canPlayAudio = true;
}).catch(function(error) {
if (SDK.canPlayAudio == null) {
SDK.canPlayAudio = false;
var playButton = document.createElement('div');
var html = "
";
playButton.innerHTML = html;
SDK.appendChild(baseRoot, playButton);
setTimeout(function() {
baseRoot.getElementById("sdkplaybutton").style.display = "none";
}, 10000);
SDK.playInitAudio = function() {
if (SDK.playInitVideo != null) {
SDK.playInitVideo();
} else {
SDK.audio = new Audio(file);
SDK.currentAudio = SDK.audio;
SDK.currentAudio.onended = function() {
SDK.currentAudio = null;
};
SDK.canPlayAudio = true;
SDK.audio.play();
baseRoot.getElementById("sdkplaybutton").style.display = "none";
var sdkvideoplaybutton2 = baseRoot.getElementById("sdkvideoplaybutton2");
if (sdkvideoplaybutton2 != null) {
sdkvideoplaybutton2.style.display = "none";
}
}
}
}
});
}
return audio;
}
SDK.playChime = true;
/**
* Play the chime sound.
*/
SDK.chime = function() {
if (SDK.playChime) {
this.play(SDK.url + '/chime.mp3', null, document);
SDK.playChime = false;
var timer = setInterval(function () {
SDK.playChime = true;
clearInterval(timer);
}, 1000);
}
}
/**
* Convert the text to speech and play it either using the browser native TTS support, or as server generated an audio file.
* The voice is optional and can be any voice supported by the server (see the voice page for a list of voices).
* For native voices a language code can be given.
* If the browser supports TTS the native voice will be used by default.
*/
SDK.tts = function(text, voice, provider, lang, nativeVoiceName, mod, apiKey, apiEndpoint, baseRoot) {
try {
if ((provider == true || provider == 'html5' || provider == 'responsive' || (provider == null && voice == null)) && SDK.speechSynthesis) {
var utterance = null;
if ('SpeechSynthesisUtterance' in window) {
utterance = new SpeechSynthesisUtterance(text);
} else {
utterance = new SpeechSynthesisUtterance2(text);
}
SDK.nativeTTS(utterance, lang, nativeVoiceName, apiKey, apiEndpoint, baseRoot);
} else {
var url = SDK.rest + '/form-speak?&text=';
url = url + encodeURIComponent(text);
url = url + '&provider=' + provider;
if (nativeVoiceName != null && provider != null && provider != "botlibre") {
url = url + '&voice=' + nativeVoiceName;
} else if (voice != null) {
url = url + '&voice=' + voice;
}
if (mod != null) {
url = url + '&mod=' + mod;
}
if (SDK.applicationId != null) {
url = url + '&application=' + SDK.applicationId;
}
var request = new XMLHttpRequest();
var self = this;
request.onreadystatechange = function() {
if (request.readyState != 4) return;
if (request.status != 200) {
console.log('Error: Speech web request failed');
return;
}
SDK.play(SDK.url + "/" + request.responseText, null, baseRoot);
}
request.open('GET', url, true);
request.send();
}
} catch (error) {
console.log('Error: Speech web request failed');
}
}
/**
* Use the ResponsiveVoice API.
*/
SDK.responsiveVoiceTTS = function(utterance, lang, voice) {
var events = {};
try {
SDK.pauseSpeechRecognition();
if (voice == null || voice == "") {
voice = "US English Female";
}
if (utterance.onend != null) {
events.onend = utterance.onend;
}
if (SDK.recognitionActive) {
events.onend = function() {
SDK.startSpeechRecognition();
if (utterance.onend != null) {
utterance.onend();
}
}
}
if (utterance.onstart != null) {
events.onstart = utterance.onstart;
}
responsiveVoice.speak(utterance.text, voice, events);
} catch (error) {
console.log(error);
}
}
/**
* Use the QQ Speech API.
*/
SDK.qqSpeechTTS = function(utterance, lang, voice, baseRoot) {
try {
SDK.pauseSpeechRecognition();
var url = SDK.rest + '/form-speak?&text=';
url = url + encodeURIComponent(utterance.text);
if (SDK.applicationId != null) {
url = url + '&application=' + SDK.applicationId;
}
if (SDK.speechInstance != null) {
url = url + '&instance=' + SDK.speechInstance;
}
if(SDK.speechType == "avatar") {
url = url + '&embeddedAvatar=true';
}
if (voice != null) {
url = url + '&voice=' + voice;
}
url = url + '&provider=qq';
var request = new XMLHttpRequest();
var self = this;
request.onreadystatechange = function() {
if (request.readyState != 4) return;
if (request.status != 200) {
console.log('Error: QQ Speech web request failed.');
return;
}
var audio = SDK.play(SDK.url + "/" + request.responseText, null, baseRoot);
audio.onplay = utterance.onstart;
audio.onended = utterance.onend;
}
request.open('GET', url, true);
request.send();
} catch (error) {
console.log(error);
}
}
/**
* Speak the native utterance first setting the voice and language.
*/
SDK.nativeTTS = function(utterance, lang, voice, apiKey, apiEndpoint, baseRoot) {
if (baseRoot == null) {
baseRoot = document;
}
if (SDK.speechRate != null) {
utterance.rate = SDK.speechRate;
}
if (SDK.speechPitch != null) {
utterance.pitch = SDK.speechPitch;
}
if (SDK.responsiveVoice) {
SDK.responsiveVoiceTTS(utterance, lang, voice);
return;
}
else if (SDK.qqSpeech) {
SDK.qqSpeechTTS(utterance, lang, voice, baseRoot);
return;
}
if (lang == null) {
lang = SDK.lang;
}
SDK.pauseSpeechRecognition();
if (SDK.recognitionActive) {
utterance.addEventListener("end", function() {
SDK.startSpeechRecognition();
});
}
speechSynthesis.cancel();
if (lang == null && voice == null) {
// Events don't always get fired unless this is done...
setTimeout(function() {
speechSynthesis.speak(utterance);
}, 100);
return;
}
speechSynthesis.lang = lang;
var voices = speechSynthesis.getVoices();
var foundVoice = null;
var foundLang = null;
var spoken = false;
if (voices.length == 0) {
speechSynthesis.onvoiceschanged = function() {
if (spoken) {
return;
}
voices = speechSynthesis.getVoices();
for (i = 0; i < voices.length; i++) {
if (voice != null && (voice.length != 0) && voices[i].name.toLowerCase().indexOf(voice.toLowerCase()) != -1) {
if (foundVoice == null || voices[i].name == voice) {
foundVoice = voices[i];
}
} else if (lang != null && (lang.length != 0) && voices[i].lang.toLowerCase().indexOf(lang.toLowerCase()) != -1) {
if (foundLang == null || voices[i].lang == lang) {
foundLang = voices[i];
}
}
}
if (foundVoice != null) {
utterance.voice = foundVoice;
} else if (foundLang != null) {
utterance.voice = foundLang;
}
spoken = true;
setTimeout(function() {
speechSynthesis.speak(utterance);
},100);
};
} else {
for (i = 0; i < voices.length; i++) {
if (voice != null && (voice.length != 0) && voices[i].name.toLowerCase().indexOf(voice.toLowerCase()) != -1) {
if (foundVoice == null || voices[i].name == voice) {
foundVoice = voices[i];
}
} else if (lang != null && (lang.length != 0) && voices[i].lang.toLowerCase().indexOf(lang.toLowerCase()) != -1) {
if (foundLang == null || voices[i].lang == lang) {
foundLang = voices[i];
}
}
}
if (foundVoice != null) {
utterance.voice = foundVoice;
} else if (foundLang != null) {
utterance.voice = foundLang;
}
setTimeout(function() {
speechSynthesis.speak(utterance);
},100);
}
}
/**
* Allow text to be translated into another language is the interface elements.
*/
SDK.translator = null;
SDK.translate = function(text) {
if (SDK.translator == null) {
SDK.translator = SDK.translators[SDK.lang];
if (SDK.translator == null) {
SDK.translator = {};
}
}
var translated = SDK.translator[text];
if (translated != null) {
return translated;
}
return text
}
SDK.translators = {
"pt" : {
"Yes" : "Sim",
"No" : "Não",
"Name" : "Nome",
"Email" : "O email",
"Phone" : "Telemóvel",
"Connect" : "Ligar",
"Speech" : "Discurso",
"Enter name" : "Insira o nome",
"Chat Log" : "Registro de bate-papo",
"Choose Language" : "Escolha o seu idioma",
"Enter valid email" : "Digite e-mail válido",
"Ping server" : "Servidor Ping",
"Flag user" : "Flag user",
"Whisper user" : "Usuário Whisper",
"Request private" : "Pedido privado",
"Clear log" : "Log clara",
"Accept private" : "Aceite privado",
"Send image" : "Enviar imagem",
"Send file" : "Enviar arquivo",
"Email Chat Log" : "Registro de bate-papo por email",
"Chime" : "Chime",
"Exit chat" : "Sair do bate-papo",
"Text to speech" : "Texto para fala",
"Speech recognition" : "Reconhecimento de fala",
"Speech Recognition" : "Reconhecimento de fala",
"Quit private channel" : "Saia do canal privado",
"Quit private or channel" : "Sair privado ou canal",
"Would you like a copy of the chat log sent to your email?" : "Gostaria de uma cópia do registro de bate-papo enviado para o seu e-mail?"
},
"fr" : {
"Yes" : "Oui",
"No" : "Non",
"Name" : "Prénom",
"Email" : "Email",
"Phone" : "Téléphone",
"Connect" : "Relier",
"Speech" : "Discours",
"Enter name" : "Entrez le nom",
"Chat Log" : "Journal de chat",
"Choose Language" : "Choisir la langue",
"Enter valid email" : "Entrez une adresse email valide",
"Ping server" : "Serveur ping",
"Flag user" : "Utilisateur du drapeau",
"Whisper user" : "Whisper utilisateur",
"Request private" : "Demander privé",
"Clear log" : "Effacer le journal",
"Accept private" : "Accepter privé",
"Send image" : "Envoyer une image",
"Send file" : "Envoyer le fichier",
"Email Chat Log" : "Journal de messagerie électronique",
"Chime" : "Carillon",
"Exit chat" : "Quitter le chat",
"Text to speech" : "Texte pour parler",
"Speech recognition" : "Reconnaissance vocale",
"Speech Recognition" : "Reconnaissance vocale",
"Quit private channel" : "Quitter la chaîne privée",
"Quit private or channel" : "Quitter privé ou canal",
"Would you like a copy of the chat log sent to your email?" : "Souhaitez-vous recevoir une copie du journal de chat envoyé à votre adresse e-mail?"
},
"es" : {
"Yes" : "Sí",
"No" : "No",
"Name" : "Nombre",
"Email" : "Email",
"Phone" : "Teléfono",
"Connect" : "Conectar",
"Speech" : "Discurso",
"Enter name" : "Ingrese el nombre",
"Chat Log" : "Registro de chat",
"Choose Language" : "Elija el idioma",
"Enter valid email" : "Ingrese un correo electrónico válido",
"Ping server" : "Servidor Ping",
"Flag user" : "Usuario de bandera",
"Whisper user" : "Usuario de Whisper",
"Request private" : "Solicitud privada",
"Clear log" : "Borrar registro",
"Accept private" : "Aceptar privado",
"Send image" : "Enviar imagen",
"Send file" : "Enviar archivo",
"Email Chat Log" : "Registro de chat de correo electrónico",
"Chime" : "Campaneo",
"Exit chat" : "Salir de chat",
"Text to speech" : "Texto a voz",
"Speech recognition" : "Reconocimiento de voz",
"Speech Recognition" : "Reconocimiento de voz",
"Quit private channel" : "Salir del canal privado",
"Quit private or channel" : "Salir de privado o canal",
"Would you like a copy of the chat log sent to your email?" : "Desea enviar un mensaje a su dirección de correo electrónico?"
},
"de" : {
"Yes" : "Ja",
"No" : "Nein",
"Name" : "Name",
"Email": "Email",
"Phone" : "Telefon",
"Connect" : "Verbinden",
"Speech" : "Rede",
"Enter name" : "Name eingeben",
"Chat Log" : "Chat Protokoll",
"Choose Language" : "Wähle eine Sprache",
"Enter valid email" : "Geben Sie gültige E-Mail-Adresse ein",
"Ping server" : "Ping-Server",
"Flag user" : "Benutzer kennzeichnen",
"Whisper user" : "Flüstern Benutzer",
"Request private" : "Privat anfragen",
"Clear log" : "Protokoll löschen",
"Accept private" : "Akzeptiere privat",
"Send image" : "Bild senden",
"Send file" : "Datei senden",
"Email Chat Log" : "E-Mail-Chatprotokoll",
"Chime" : "Glockenspiel",
"Exit chat" : "Chat beenden",
"Text to speech" : "Text zu Sprache",
"Speech recognition" : "Spracherkennung",
"Speech Recognition" : "Spracherkennung",
"Quit private channel" : "Beenden Sie den privaten Kanal",
"Quit private or channel" : "Beenden Sie private oder Kanal",
"Would you like a copy of the chat log sent to your email?" : "Möchten Sie eine Kopie des Chat-Protokolls an Ihre E-Mail-Adresse senden?"
},
"zh" : {
"Yes" : "是",
"No" : "沒有",
"Name" : "名稱",
"Email" : "電子郵件",
"Phone" : "電話",
"Connect" : "連",
"Speech" : "言語",
"Enter name" : "輸入名字",
"Chat Log" : "聊天記錄",
"Choose Language" : "選擇語言",
"Enter valid email" : "輸入有效的郵件",
"Ping server" : "叮噹服務器",
"Flag user" : "標記用戶",
"Whisper user" : "耳語用戶",
"Request private" : "請求私人",
"Clear log" : "清除日誌",
"Accept private" : "接受私人",
"Send image" : "發送圖像",
"Send file" : "發送文件",
"Email Chat Log" : "電子郵件聊天日誌",
"Chime" : "鐘",
"Exit chat" : "退出聊天",
"Text to speech" : "文字轉語音",
"Speech recognition" : "語音識別",
"Speech Recognition" : "語音識別",
"Quit private channel" : "退出私人頻道",
"Quit private or channel" : "退出私人或頻道",
"Would you like a copy of the chat log sent to your email?" : "你想要發送到你的電子郵件的聊天記錄的副本嗎?"
},
"ja" : {
"Yes" : "はい",
"No" : "いいえ",
"Name" : "名",
"Email" : "Eメール",
"Phone" : "電話",
"Connect" : "接続する",
"Disconnect" : "切断する",
"Speech" : "スピーチ",
"Enter name" : "名前を入力",
"Chat Log" : "チャットログ",
"Clear log" : "ログをクリアする",
"Choose Language" : "言語を選択する",
"Enter valid email" : "有効なメールアドレスを入力",
"Ping server" : "リングサーバー",
"Flag user" : "ユーザーにフラグを設定する",
"Whisper user" : "ささやくユーザー",
"Request private" : "プライベートをリクエストする",
"Accept private" : "プライベートを受け入れる",
"Send image" : "画像を送る",
"Send file" : "ファイルを送信",
"Upload image" : "画像をアップロードする",
"Upload file" : "ファイルをアップロードする",
"Email Chat Log" : "メールチャットログ",
"Chime" : "チャイム",
"Exit chat" : "チャットを終了",
"Text to speech" : "スピーチテキスト",
"Speech recognition" : "音声認識",
"Speech Recognition" : "音声認識",
"Quit private channel" : "プライベートチャンネルを終了する",
"Quit private or channel" : "プライベートまたはチャンネルを終了する",
"Would you like a copy of the chat log sent to your email?" : "チャットログのコピーをメールに送信しますか?"
},
"ar" : {
"Yes" : "نعم فعلا",
"No" : "لا",
"Name" : "اسم",
"Email" : "البريد الإلكتروني",
"Phone" : "",
"Connect" : "هاتف",
"Disconnect" : "قطع الاتصال",
"Speech" : "خطاب",
"Enter name" : "أدخل الاسم",
"Chat Log" : "سجل الدردشة",
"Clear log" : "سجل نظيف",
"Choose Language" : "اختر اللغة",
"Enter valid email" : "أدخل بريد إلكتروني صالحا",
"Ping server" : "خادم بينغ",
"Flag user" : "مستخدم العلم",
"Whisper user" : "الهمس المستخدم",
"Request private" : "طلب خاص",
"Clear Log" : "سجل نظيف",
"Accept private" : "قبول خاص",
"Send image" : "إرسال صورة",
"Send file" : "إرسال ملف",
"Email Chat Log" : "سجل الدردشة عبر البريد الإلكتروني",
"Chime" : "قرع الأجراس",
"Exit chat" : "الخروج من الدردشة",
"Text to speech" : "النص إلى الكلام",
"Speech Recognition" : "التعرف على الكلام",
"Quit private channel" : "إنهاء القناة الخاصة",
"Quit private or channel": "إنهاء خاص أو قناة",
"Would you like a copy of the chat log sent to your email?" : "هل تريد إرسال نسخة من سجل الدردشة إلى بريدك الإلكتروني؟"
},
"ru" : {
"Yes" : "Да",
"No" : "Hет",
"Name" : "Имя",
"Email": "Эл. почта",
"Phone" : "Телефон",
"Connect" : "Cоединить",
"Disconnect" : "Отключить",
"Speech" : "Pечь",
"Enter name" : "Введите имя",
"Chat Log" : "Журнал чата",
"Choose Language" : "Выберите язык",
"Enter valid email" : "Введите действующий адрес электронной почты",
"Ping server" : "Пинг сервер",
"Flag user" : "Oтметить пользователя",
"Whisper user" : "Прошептать пользователю",
"Request private" : "Частный запрос",
"Clear log" : "Очистить журнал",
"Clear Log" : "Очистить журнал",
"Accept private" : "Принять конфиденциальнo",
"Send image" : "Отправить изображение",
"Send file" : "Отправить файл",
"Email Chat Log" : "Oтправить журнал чата по электронной почте",
"Chime" : "Звонок",
"Exit chat" : "Выход из чата",
"Text to speech" : "Текст в речь",
"Speech Recognition" : "Распознавание речи",
"Quit private channel" : "Выйти из частного канала",
"Quit private or channel": "Выйти из частного канала",
"Would you like a copy of the chat log sent to your email?" : "Oтправить копю журнала чата на ваш адрес электронной почты?"
}
}
/**
* Detect Chrome browser.
*/
SDK.isChrome = function() {
var agent = navigator.userAgent.toLowerCase();
return agent.indexOf('chrome') != -1 && agent.indexOf('edg') == -1;
}
/**
* Detect Firefox browser.
*/
SDK.isFirefox = function() {
return navigator.userAgent.toLowerCase().indexOf('firefox') != -1;
}
/**
* Detect Safari browser.
*/
SDK.isSafari = function() {
var agent = navigator.userAgent.toLowerCase();
return agent.indexOf('safari') != -1 && agent.indexOf('edg') == -1;
}
/**
* Detect Internet Explorer browser.
*/
SDK.isMSIE = function() {
var agent = navigator.userAgent.toLowerCase();
return agent.indexOf('msie') != -1 || agent.indexOf('trident') != -1;
}
/**
* Detect Edge browser.
*/
SDK.isEdge = function() {
return navigator.userAgent.toLowerCase().indexOf('edg') != -1;
}
/**
* Detect mobile browser.
*/
SDK.isMobile = function() {
if (navigator.userAgent.match(/Android/i)
|| navigator.userAgent.match(/webOS/i)
|| navigator.userAgent.match(/iPhone/i)
|| navigator.userAgent.match(/iPad/i)
|| navigator.userAgent.match(/iPod/i)
|| navigator.userAgent.match(/BlackBerry/i)
|| navigator.userAgent.match(/Windows Phone/i)) {
return true;
} else {
return false;
}
}
/**
* Detect iPhone OS.
*/
SDK.isIPhone = function() {
if (navigator.userAgent.match(/iPhone/i)) {
return true;
}
return false;
}
/**
* Detect Mac OS.
*/
SDK.isMac = function() {
return navigator.platform.toLowerCase().indexOf('mac') != -1;
}
SDK.hd = false;
SDK.format = (SDK.isChrome() || SDK.isFirefox()) ? "webm" : "mp4";
// // Safari displays HTML5 video very poorly on iPhone.
// if (SDK.isSafari() && SDK.isIPhone()) {
// SDK.format = "img";
// }
/**
* Insert the text into the input field.
*/
SDK.insertAtCaret = function(element, text) {
if (document.selection) {
element.focus();
var sel = document.selection.createRange();
sel.text = text;
element.focus();
} else if (element.selectionStart || element.selectionStart == 0) {
var startPos = element.selectionStart;
var endPos = element.selectionEnd;
var scrollTop = element.scrollTop;
element.value = element.value.substring(0, startPos) + text + element.value.substring(endPos, element.value.length);
element.focus();
element.selectionStart = startPos + text.length;
element.selectionEnd = startPos + text.length;
element.scrollTop = scrollTop;
} else {
element.value += text;
element.focus();
}
}
/**
* Get the document body, and create one if missing.
*/
SDK.body = function() {
var body = document.body || document.getElementsByTagName('body')[0];
if (body == null) {
body = document.createElement("body");
document.body = body;
}
return body;
}
SDK.appendChild = function(baseRoot, child) {
if (baseRoot == document) {
baseRoot = SDK.body();
}
baseRoot.appendChild(child);
}
/**
* Fix innerHTML for IE and Safari.
*/
SDK.innerHTML = function(element) {
var html = element.innerHTML;
if (html == null) {
var serializer = new XMLSerializer();
html = "";
for (var index = 0; index < element.childNodes.length; index++) {
html = html + serializer.serializeToString(element.childNodes[index]);
}
if (html.indexOf(""") != -1) {
html = html.replace(/"/g, '"');
}
}
var index = html.indexOf("<");
var index2 = html.indexOf(">")
if (index != -1 && index2 > index) {
html = html.replace(/</g, "<");
html = html.replace(/>/g, ">");
}
if (html.indexOf("&") != -1) {
html = html.replace(/&/g, "&");
}
return html;
}
/**
* Strip HTML tags from text.
* Return plain text.
*/
SDK.stripTags = function(html) {
var element = document.createElement("p");
element.innerHTML = html;
SDK.removeTags(element);
return element.innerText || element.textContent;
}
SDK.removeTags = function(node) {
if (node.className == 'nospeech' || node.tagName == 'SCRIPT' || node.tagName == 'SELECT' || node.tagName == 'BUTTON' || node.tagName == 'OPTION') {
node.parentNode.removeChild(node);
} else {
var index = 0;
var childNodes = node.childNodes;
var children = [];
while (index < childNodes.length) {
children[index] = childNodes[index];
index++;
}
var index = 0;
while (index < children.length) {
SDK.removeTags(children[index]);
index++;
}
}
return node;
}
/**
* Replace reserved HTML character with their HTML escape codes.
*/
SDK.escapeHTML = function(html) {
return html.replace(/&/g, "&")
.replace(//g, ">")
.replace(/"/g, """)
.replace(/'/g, "'");
}
SDK.unescapeHTML = function(html) {
return html.replace(/&/g, "&")
.replace(/</g, "<")
.replace(/>/g, ">")
.replace(/"/g, "\"")
.replace(/'/g, "'")
.replace(/"/g, "\"");
}
/**
* Replace URL and email references in the text with HTML links.
*/
SDK.linkURLs = function(text) {
var http = text.indexOf("http") != -1;
var www = text.indexOf("www.") != -1;
var email = text.indexOf("@") != -1;
if (!http && !www && !email) {
return text;
}
if (text.indexOf("<") != -1 && text.indexOf(">") != -1) {
return text;
}
if (http) {
var regex = /\b(?:https?|ftp|file):\/\/[a-z0-9-+&@#\/%?=~_|!:,.;]*[a-z0-9-+&@#\/%=~_|]/gim;
text = text.replace(regex, function(url, b, c) {
var lower = url.toLowerCase();
if (lower.indexOf(".png") != -1 || lower.indexOf(".jpg") != -1 || lower.indexOf(".jpeg") != -1 || lower.indexOf(".gif") != -1) {
return '';
} else if (lower.indexOf(".mp4") != -1 || lower.indexOf(".webm") != -1 || lower.indexOf(".ogg") != -1) {
return '';
} else if (lower.indexOf(".wav") != -1 || lower.indexOf(".mp3") != -1) {
return '';
} else {
return '' + url + '';
}
});
} else if (www) {
var regex = /((www\.)[^\s]+)/gim;
text = text.replace(regex, function(url, b, c) {
return '' + url + '';
});
}
// http://, https://, ftp://
//var urlPattern = /\b(?:https?|ftp):\/\/[a-z0-9-+&@#\/%?=~_|!:,.;]*[a-z0-9-+&@#\/%=~_|]/gim;
// www.
// var wwwPattern = /(^|[^\/])(www\.[\S]+(\b|$))/gim;
// name@domain.com
if (email) {
var emailPattern = /(([a-zA-Z0-9_\-\.]+)@[a-zA-Z_]+?(?:\.[a-zA-Z]{2,6}))+/gim;
text = text.replace(emailPattern, '$1');
}
return text;
}
/**
* Enable speech recognition if supported by the browser, and insert the voice to text to the input field.
* Optionally call click() on the button.
*/
SDK.registerSpeechRecognition = function(input, button) {
if (SDK.recognition == null) {
if ('webkitSpeechRecognition' in window) {
SDK.recognition = new webkitSpeechRecognition();
if (SDK.lang != null) {
SDK.recognition.lang = SDK.lang;
}
SDK.recognition.continuous = true;
SDK.recognition.onresult = function (event) {
for (var i = event.resultIndex; i < event.results.length; ++i) {
if (event.results[i].isFinal) {
SDK.insertAtCaret(input, event.results[i][0].transcript);
}
}
if (button != null && button.click != null) {
button.click();
} else if (button != null) {
button();
}
};
} else {
return;
}
}
}
SDK.startSpeechRecognition = function() {
if (SDK.recognition != null) {
if (SDK.lang != null) {
SDK.recognition.lang = SDK.lang;
}
SDK.recognition.start();
SDK.recognitionActive = true;
}
}
SDK.pauseSpeechRecognition = function() {
if (SDK.recognition != null) {
SDK.recognition.stop();
}
}
SDK.stopSpeechRecognition = function() {
if (SDK.recognition != null) {
SDK.recognition.stop();
SDK.recognitionActive = false;
}
}
SDK.popupwindow = function(url, title, w, h) {
var wleft = (screen.width)-w-100;
var wtop = (screen.height)-h-200;
window.open(url, title, 'scrollbars=yes, resizable=yes, toolbar=no, location=no, directories=no, status=no, menubar=no, copyhistory=no, width='+w+', height='+h+', top='+wtop+', left='+wleft);
return false;
}
SDK.dataURLToBlob = function(dataURL) {
var marker = ';base64,';
if (dataURL.indexOf(marker) == -1) {
var parts = dataURL.split(',');
var contentType = parts[0].split(':')[1];
var raw = parts[1];
return new Blob([raw], {type: contentType});
}
var parts = dataURL.split(marker);
var contentType = parts[0].split(':')[1];
var raw = window.atob(parts[1]);
var rawLength = raw.length;
var blobarray = new Uint8Array(rawLength);
for (var i = 0; i < rawLength; ++i) {
blobarray[i] = raw.charCodeAt(i);
}
return new Blob([blobarray], {type: contentType});
}
SDK.isAlphaNumeric = function(text) {
var regex = /[`!@#$%^&*()_\+\-=\[\]{};':"\\|,.~<>\/?]+/;
return !regex.test(text);
}
SDK.uploadImage = function(fileInput, url, width, height, properties, onFinish) {
if (window.File && window.FileReader && window.FileList && window.Blob) {
// Copy over form properties.
if (properties == null) {
properties = {};
}
if (fileInput.form != null) {
var data = new FormData(fileInput.form);
var entries = data.entries();
var next = entries.next();
while (!next.done) {
var key = next.value[0];
var value = next.value[1];
if (key != 'file') {
if (properties[key] == null) {
properties[key] = value;
}
}
next = entries.next();
}
}
var files = fileInput.files;
var index = 0;
// Need to process images one by one to avoid resource limits from async
var nextImage = function() {
SDK.resizeAndUploadImage(files[index], url, width, height, properties, ((index == (files.length - 1) ? onFinish : nextImage)))
index++;
}
nextImage();
return false;
} else {
alert('The File APIs are not fully supported in this browser.');
return false;
}
}
SDK.resizeAndUploadImage = function(file, url, width, height, properties, onFinish) {
var reader = new FileReader();
reader.onloadend = function() {
var tempImg = new Image();
tempImg.src = reader.result;
tempImg.onload = function() {
var MAX_WIDTH = width;
var MAX_HEIGHT = height;
if (width == null) {
MAX_WIDTH = tempImg.width;
}
if (height == null) {
MAX_HEIGHT = tempImg.height;
}
var tempW = tempImg.width;
var tempH = tempImg.height;
if (tempW > MAX_WIDTH) {
tempH *= MAX_WIDTH / tempW;
tempW = MAX_WIDTH;
}
if (tempH > MAX_HEIGHT) {
tempW *= MAX_HEIGHT / tempH;
tempH = MAX_HEIGHT;
}
var canvas = document.createElement('canvas');
canvas.width = tempW;
canvas.height = tempH;
var ctx = canvas.getContext("2d");
ctx.fillStyle = '#fff';
ctx.fillRect(0, 0, canvas.width, canvas.height);
ctx.drawImage(this, 0, 0, tempW, tempH);
var dataUrl = canvas.toDataURL('image/jpeg');
var blob = SDK.dataURLToBlob(dataUrl);
var formData = new FormData();
if (properties != null) {
for (property in properties) {
formData.append(property, properties[property]);
}
}
formData.append('file', blob, file.name);
var request = new XMLHttpRequest();
request.onreadystatechange = function() {
if (request.readyState != 4) {
return;
}
if (onFinish != null) {
onFinish();
}
}
request.open("POST", url);
request.send(formData);
}
}
reader.readAsDataURL(file);
}
/**
* Open a JQuery error message dialog.
*/
SDK.showError = function(message, title) {
if (title == null) {
title = "Error";
}
$("").html(message).dialog({
title: title,
resizable: false,
modal: true,
buttons: [
{
text: "OK",
click: function() {
$(this).dialog("close");
},
class: "okbutton"
}
]
});
}
/**
* Open a JQuery confirm dialog.
*/
SDK.showConfirm = function(message, title, onYes, onNo) {
if (title == null) {
title = "Confirm";
}
$("").html(message).dialog({
title: title,
resizable: false,
modal: true,
buttons: {
"Yes": function() {
onYes();
$(this).dialog("close");
},
"No": function() {
onNo();
$(this).dialog("close");
}
}
});
}
/**
* Evaluate any script tags in the node's descendants.
* This is required when innerHtml contains script nodes as they are not evaluated.
*/
SDK.evalScripts = function(node) {
if (node.tagName == 'SCRIPT') {
var script = document.createElement("script");
script.text = node.innerHTML;
for (var index = node.attributes.length-1; index >= 0; i--) {
script.setAttribute(node.attributes[index].name, node.attributes[index].value);
}
node.parentNode.replaceChild(script, node);
} else {
var index = 0;
var children = node.childNodes;
while (index < children.length) {
SDK.evalScripts(children[index]);
index++;
}
}
return node;
}
/**
* Remove any script tags from the node.
*/
SDK.removeScripts = function(node) {
if (node.tagName == 'SCRIPT') {
node.parentNode.removeChild(node);
} else {
var index = 0;
var children = node.childNodes;
while (index < children.length) {
SDK.removeScripts(children[index]);
index++;
}
}
return node;
}
/**
* Add a stylesheet link to the page.
*/
SDK.addStylesheet = function(fileName) {
var head = document.head;
var link = document.createElement('link');
link.type = 'text/css';
link.rel = 'stylesheet';
link.href = fileName;
head.appendChild(link);
}
/**
* Add a style tag to the page.
*/
SDK.addStyle = function(css) {
var style = document.createElement('style');
style.type = 'text/css';
if (style.styleSheet) {
style.styleSheet.cssText = css;
} else {
style.appendChild(document.createTextNode(css));
}
SDK.body().appendChild(style);
}
/**
* Graphics upload dialog and shared repositry browser.
* This provides a generic media upload dialog with many features:
*
*
Upload dialog UI
*
Locally resize images before upload
*
Upload from a web URL
*
Upload a media file from a shared graphics repository
*
\n";
}
if (this.showFile) {
if (this.showBrowse) {
html = html + "\n";
}
var multipleStr = "";
if (this.multiple) {
multipleStr = "multiple='multiple'";
}
html = html
+ "
\n";
graphicDiv.innerHTML = html;
var img = document.createElement('img');
img.setAttribute('src', urlprefix + result.avatar);
div.appendChild(graphicDiv);
}
});
}
}
GraphicsUploader.map = {};
GraphicsUploader.tags = [];
GraphicsUploader.categories = [];
/**
* Open a media uploader dialog initialized with a form.
* The dialog will use the form's action to upload media as 'file' for a file, or 'upload-url' for a URL.
* The form should define an ID if to be used on multiple forms in the same document.
* This can be used on the onclick on an input element to open the dialog i.e.
* This will create a hidden input of type file ('file'), and a hidden input of type text ('upload-url'), these will be passed to your server when the dialog submits the form.
*/
GraphicsUploader.openUploadDialog = function(form, title, showFile, showURL, showBrowse, multiple) {
var id = form.getAttribute('id');
var prefix = "uploader-";
var dialogId = "graphics-uploader";
var browserId = "graphics-browser";
if (id == null) {
id = "uploader";
} else {
prefix = id + '-' + prefix;
dialogId = id + '-' + dialogId;
browserId = id + '-' + browserId;
}
var uploader = GraphicsUploader.map[id];
if (uploader == null) {
uploader = new GraphicsUploader();
uploader.multiple = multiple;
var multipleStr = "";
if (multiple) {
multipleStr = "multiple='multiple'";
}
GraphicsUploader.map[id] = uploader;
var div = document.createElement('div');
var html =
"\n"
+ "";
div.innerHTML = html;
form.appendChild(div);
if (title != null) {
uploader.dialogTitle = title;
}
if (showFile != null) {
uploader.showFile = showFile;
}
if (showURL != null) {
uploader.showURL = showURL;
}
if (showBrowse != null) {
uploader.showBrowse = showBrowse;
}
uploader.prefix = prefix;
uploader.dialogId = dialogId;
uploader.id= browserId;
uploader.fileInput = document.getElementById(id + 'file-input');
uploader.urlInput = document.getElementById(id + 'url-input');
uploader.uploadURL = form.action;
// Copy over form properties.
uploader.uploadFormProperties = {};
var data = new FormData(form);
var entries = data.entries();
var next = entries.next();
while (!next.done) {
var key = next.value[0];
var value = next.value[1];
uploader.uploadFormProperties[key] = value;
next = entries.next();
}
}
uploader.openUploadDialog();
return false;
}
/**
* Avatar browser dialog.
*/
function AvatarBrowser(formInput, sdkUser) {
this.id = "avatar-browser";
this.title = "Avatar Browser";
this.browserClass = "dialog";
this.dialogId = "avatar-selector";
this.dialogTitle = "Choose Avatar";
this.dialogClass = "dialog";
this.formInput = formInput;
this.prefix = "Selector-";
this.sdk = null;
/**
* Open JQuery browser dialog.
*/
this.openBrowser = function() {
var browser = document.getElementById(this.id);
if (browser != null) {
$( '#' + this.id ).remove();
}
this.renderBrowser();
$( '#' + this.id ).dialog("open");
this.fetchAvatar();
}
/**
* Render JQuery browser dialog.
*/
this.renderBrowser = function() {
var browser = document.createElement('div');
browser.setAttribute('id', this.id);
browser.setAttribute('title', this.title);
browser.setAttribute('class', this.browserClass);
browser.style.display = "none";
var self = this;
AvatarBrowser.updateSearch = function() {
self.fetchAvatar();
}
var height = window.innerHeight - (window.innerHeight * 0.2);
var width = window.innerWidth - (window.innerWidth * 0.2);
var html =
"\n"
+ "
"
+ "
"
+ " "
+ " "
+ " "
+ " "
+ "
"
+ "
Search
"
+ "
Categories
"
+ "
Tags
"
+ "
Sort
\n"
+ "
Rating
\n"
+ "
\n"
+ "\n"
+ "
\n"
+ "
\n";
browser.innerHTML = html;
SDK.body().appendChild(browser);
if (this.sdk == null) {
this.sdk = new SDKConnection();
}
var autocompleteEvent = function(event) {
var self = this;
$(self).autocomplete('search', '');
}
if (AvatarBrowser.tags.length == 0) {
var contentConfig = new ContentConfig();
// TODO fix domain
contentConfig.domain = "1";
contentConfig.type = "Avatar";
this.sdk.fetchTags(contentConfig, function(results) {
AvatarBrowser.tags = results;
$( "#" + self.prefix + "browse-tags" ).autocomplete({ source: AvatarBrowser.tags, minLength: 0, appendTo: $("#" + self.prefix + "browse-tags").parent() }).on('focus', autocompleteEvent);
});
} else {
$( "#" + this.prefix + "browse-tags" ).autocomplete({ source: AvatarBrowser.tags, minLength: 0, appendTo: $("#" + self.prefix + "browse-tags").parent() }).on('focus', autocompleteEvent);
}
if (AvatarBrowser.categories.length == 0) {
var contentConfig = new ContentConfig();
// TODO fix domain
contentConfig.domain = "1";
contentConfig.type = "Avatar";
this.sdk.fetchCategories(contentConfig, function(results) {
AvatarBrowser.categories = results;
$( "#" + self.prefix + "browse-categories" ).autocomplete({ source: AvatarBrowser.categories, minLength: 0, appendTo: $("#" + self.prefix + "browse-categories").parent() }).on('focus', autocompleteEvent);
});
} else {
$( "#" + this.prefix + "browse-categories" ).autocomplete({ source: AvatarBrowser.categories, minLength: 0, appendTo: $("#" + self.prefix + "browse-categories").parent() }).on('focus', autocompleteEvent);
}
var keyPressed = function search(e) {
if (e.keyCode == 13) {
self.fetchAvatar();
}
}
$( "#" + this.prefix + "browse-tags" ).on("keydown", keyPressed);
$( "#" + this.prefix + "browse-categories" ).on("keydown", keyPressed);
$( "#" + this.prefix + "browse-filter" ).on("keydown", keyPressed);
$( "input[name='" + this.prefix + "browse-type']" ).on("change", () => self.fetchAvatar());
$( '#' + this.id ).dialog({
autoOpen: false,
modal: true,
height: height,
width: width,
buttons: {
"Cancel": function() {
$(this).dialog("close");
}
}
});
}
/**
* Query and display avatars.
*/
this.fetchAvatar = function() {
var browseConfig = new BrowseConfig();
browseConfig.type = "Avatar";
browseConfig.category = document.getElementById(this.prefix + 'browse-categories').value;
browseConfig.tag = document.getElementById(this.prefix + 'browse-tags').value;
browseConfig.filter = document.getElementById(this.prefix + 'browse-filter').value;
browseConfig.sort = document.getElementById(this.prefix + 'browse-sort').value;
const selectedBrowseOption = document.querySelector("input[type='radio'][name='" + this.prefix + "browse-type']:checked");
let browseType = 'Featured'; ;
if (selectedBrowseOption) {
browseType = selectedBrowseOption.value;
}
browseConfig.typeFilter = browseType;
browseConfig.contentRating = document.getElementById(this.prefix + 'browse-rating').value || "Teen";
// For now hardcode default domain, need a Workspace drop down or toggle to switch from local vs default.
browseConfig.domain = "1";
var self = this;
var urlprefix = self.sdk.credentials.url + "/";
AvatarBrowser.selectAvatar = function(avatarId) {
self.formInput.value = avatarId;
self.formInput.dispatchEvent(new Event('change'));
$( '#' + self.id ).dialog("close");
}
this.sdk.browse(browseConfig, function(results) {
var div = document.getElementById(self.prefix + "browser-div");
while (div.firstChild) {
div.removeChild(div.firstChild);
}
for (var index = 0; index < results.length; index++) {
var result = results[index];
var graphicDiv = document.createElement('div');
graphicDiv.setAttribute('id', self.prefix + 'browse-div');
graphicDiv.setAttribute('class', self.prefix + 'browse-div');
var html =
""
+ "
"
+ "\n"
+ "
"
+ "
"
+ "" + result.name + " " + result.description + " "
+ "";
if (result.categories != null && result.categories != "") {
html = html + "Categories: " + result.categories + " ";
}
if (result.tags != null && result.tags != "") {
html = html + "Tags: " + result.tags + " ";
}
if (result.license != null && result.license != "") {
html = html + "License: " + result.license + " ";
}
html = html
+ "
\n";
graphicDiv.innerHTML = html;
var img = document.createElement('img');
img.setAttribute('src', urlprefix + result.avatar);
div.appendChild(graphicDiv);
}
});
}
}
BotBrowser.map = {};
BotBrowser.tags = [];
BotBrowser.categories = [];
/**
* Credentials used to establish a connection.
* Defines the url, host, app, rest, which are all defaulted and should not need to be changed,
* Requires an application id.
* You can obtain your application id from your user details page on the hosting website.
* @class
*/
function Credentials() {
this.host = SDK.host;
this.app = SDK.app;
this.url = SDK.url;
this.rest = SDK.rest;
this.applicationId = SDK.applicationId;
}
/**
* Credentials for use with hosted services on the Bot Libre website, a free bot hosting service.
* https://www.botlibre.com
* @class
*/
function BOTlibreCredentials() {
this.DOMAIN = "www.botlibre.com";
this.APP = "";
this.PATH = "/rest/api";
this.host = this.DOMAIN;
this.app = this.APP;
this.url = "https://" + this.DOMAIN + this.APP;
this.rest = this.url + this.PATH;
this.applicationId = SDK.applicationId;
}
/**
* Credentials for use with hosted services on the Bot Libre for Business website,
* a commercial bot, live chat, chatroom, and forum, hosting service.
* https://www.botlibre.biz
* @class
*/
function BotLibreBizCredentials() {
this.DOMAIN = "www.botlibre.biz";
this.APP = "";
this.PATH = "/rest/api";
this.host = this.DOMAIN;
this.app = this.APP;
this.url = "https://" + this.DOMAIN + this.APP;
this.rest = this.url + this.PATH;
this.applicationId = SDK.applicationId;
}
/**
* Credentials for use with hosted services on the Bot Libre for Business website,
* a commercial bot, live chat, chatroom, and forum, hosting service.
* https://www.botlibre.biz
* @class
*/
function PaphusCredentials() {
this.DOMAIN = "www.botlibre.biz";
this.APP = "";
this.PATH = "/rest/api";
this.host = this.DOMAIN;
this.app = this.APP;
this.url = "https://" + this.DOMAIN + this.APP;
this.rest = this.url + this.PATH;
this.applicationId = SDK.applicationId;
}
/**
* Credentials for use with hosted services on the LIVE CHAT libre website, a free live chat, chatrooms, forum, and chat bots that learn.
* http://www.livechatlibre.com
* @class
*/
function LIVECHATlibreCredentials() {
this.DOMAIN = "www.livechatlibre.com";
this.APP = "";
this.PATH = "/rest/api";
this.host = this.DOMAIN;
this.app = this.APP;
this.url = "http://" + this.DOMAIN + this.APP;
this.rest = this.url + this.PATH;
this.applicationId = SDK.applicationId;
}
/**
* Credentials for use with hosted services on the FORUMS libre website, a free embeddable forum hosting service.
* http://www.forumslibre.com
* @class
*/
function FORUMSlibreCredentials() {
this.DOMAIN = "www.forumslibre.com";
this.APP = "";
this.PATH = "/rest/api";
this.host = this.DOMAIN;
this.app = this.APP;
this.url = "http://" + this.DOMAIN + this.APP;
this.rest = this.url + this.PATH;
this.applicationId = SDK.applicationId;
}
/**
* Listener interface for a LiveChatConnection.
* This gives asynchronous notification when a channel receives a message, or notice.
* @class
*/
function LiveChatListener() {
/**
* A user message was received from the channel.
*/
this.message = function(message) {};
/**
* An informational message was received from the channel.
* Such as a new user joined, private request, etc.
*/
this.info = function(message) {};
/**
* An error message was received from the channel.
* This could be an access error, or message failure.
*/
this.error = function(message) {};
/**
* Notification that the connection was closed.
*/
this.closed = function() {};
/**
* The channels users changed (user joined, left, etc.)
* This contains a comma separated values (CSV) list of the current channel users.
* It can be passed to the SDKConnection.getUsers() API to obtain the UserConfig info for the users.
*/
this.updateUsers = function(usersCSV) {};
/**
* The channels users changed (user joined, left, etc.)
* This contains a HTML list of the current channel users.
* It can be inserted into an HTML document to display the users.
*/
this.updateUsersXML = function(usersXML) {};
}
/**
* The WebLiveChatListener provides an integration between a LiveChatConnection and an HTML document.
* It updates the document to message received from the connection, and sends messages from the document's form.
* The HTML document requires the following elements:
* - chat - chat text input for sending messages
* - send - button for sending chat input
* - response -
paragraph for last chat message
* - console -
table for chat log, and user log
* - scroller -
div for chat log scroll pane
* - online -
table for chat user list
* @class
*/
function WebLiveChatListener() {
/** Set the caption for the button bar button. */
this.caption = null;
this.switchText = true;
this.sound = true;
this.speak = false;
/** The name of the voice to use. */
this.voice = null;
/** The name of the voice mod to use. */
this.voiceMod = null;
/** Configure if the browser's native voice TTS should be used. */
this.nativeVoice = false;
/** Set the voice name for the native voice. */
this.nativeVoiceName = null;
/** Set the language for the native voice. */
this.lang = null;
/** Enable or disable avatar (you must also set the avatar ID). */
this.avatar = false;
/** Set the avatar. */
this.avatarId = null;
/** Set if the avatar should request HD (high def) video/images. */
this.hd = null;
/** Set if the avatar should request a specific video or image format. */
this.format = null;
this.lang = null;
this.nick = "";
this.connection = null;
this.sdk = null;
/** Configure if chat should be given focus after message. */
this.focus = !SDK.isMobile();
/** Element id and class prefix. Can be used to have multiple avatars in the same page, or avoid naming collisions. */
this.prefix = "";
/** Allow the chat box button color to be set. */
this.color = "#009900";
/** Allow the user to modify style sheets. */
this.version = null;
/** Allow the chat box hover button color to be set. */
this.hoverColor = "grey";
/** Allow the chat box background color to be set. */
this.background = null;
/** Chat box width. */
this.width = 300;
/** Chat box height. */
this.height = null;
/** Chat box offset from side. */
this.offset = 30;
/** Chat Button Vertial Offset*/
this.verticalOffset = 0;
/** Print response in chat bubble. */
this.bubble = false;
/** Set the location of the button and box, one of "bottom-right", "bottom-left", "top-right", "top-left". */
this.boxLocation = "bottom-right";
/** Set styles explicitly to avoid inheriting page styles. Disable this to be able to override styles. */
this.forceStyles = true;
/** Override the URL used in the chat box popup. */
this.popupURL = null;
/** Set if the box chat log should be shown. */
this.chatLog = true;
/** Box chat loading message to display. */
this.loading = "loading...";
/** Box chat show online users option. */
this.online = false;
/** Link to online user list users to their profile page. */
this.linkUsers = true;
/** Configure message log format (table or log). */
this.chatLogType = "log";
/** Configure the chat to auto accept a bot after waiting */
this.autoAccept = null;
/** Prompt for name/email before connecting. */
this.promptContactInfo = false;
this.hasContactInfo = false;
/** Set if the back link should be displayed. */
this.backlink = SDK.backlink;
this.contactName = null;
this.contactEmail = null;
this.contactPhone = null;
this.contactInfo = "";
/** Allow the close button on the box button bar to be removed, and maximize on any click to the button bar. */
this.showClose = true;
/** Provide an email chat log menu item. */
this.emailChatLog = false;
/** Ask the user if they want an email of the chat log on close. */
this.promptEmailChatLog = false;
this.windowTitle = document.title;
this.isActive = true;
/** Variables used to get the user and bot images. */
this.botThumb = {};
this.userThumb = {};
self = this;
/** Map of user id/alias to user image. */
this.users = {};
/** Map of user id/alias to user name. */
this.userNames = {};
/** Box chat chat room option. */
this.chatroom = false;
/** Cofigure if the user name or user ids/aliases should be used. */
this.displayUserNames = true;
/** Show and hides menu bar */
this.showMenubar = true;
/** Show Box Max */
this.showBoxmax = true;
/** Show Send Image */
this.showSendImage = true;
/** Toggle Avatar / Chat Log Image Button */
this.toggleAvatar = false;
/** Css config */
this.buttoncss = "";
/** Shadow DOM root and enable. */
this.baseRoot = document;
this.enableShadowDOM = false;
/** Chat button icon */
this.icon = null;
/**
* Create an embedding bar and div in the current web page.
*/
this.createBox = function() {
if (this.prefix == "" && this.elementPrefix != null) {
this.prefix = this.elementPrefix;
}
if (this.caption == null) {
this.caption = this.instanceName;
}
var backgroundstyle = "";
var backgroundstyle2 = "";
var buttonstyle = "";
var buttonHoverStyle = "";
var hidden = "hidden";
var border = "";
if (this.backgroundIfNotChrome && (SDK.isChrome() || SDK.isFirefox())) {
this.background = null;
}
if (this.background != null) {
backgroundstyle = " style='background-color:" + this.background + "'";
hidden = "visible";
border = "border:1px;border-style:solid;border-color:black;";
} else {
border = "border:1px;border-style:solid;border-color:transparent;";
}
if (this.color != null) {
buttonstyle = "background-color:" + this.color + ";";
}
if (this.hoverColor != null) {
buttonHoverStyle = "background-color:" + this.hoverColor + ";";
}
var minWidth = "";
var divWidth = "";
var background = "";
var minHeight = "";
var divHeight = "";
var maxDivWidth = "";
var maxHeight = null;
var responseWidth = "";
var chatWidth = "";
var hideAvatar = "";
var avatarWidth = this.width;
var minAvatarWidth = "";
var scrollerHeight = this.height;
var scrollerMinHeight = "";
if (this.width != null) {
if (typeof this.width === "string") {
this.width = parseInt(this.width);
}
// Auto correct for a short window or screen (assuming square).
// 250 is total box height minus avatar.
if ((this.width + 280) > window.innerHeight) {
avatarWidth = window.innerHeight - 280;
if (avatarWidth < 100) {
hideAvatar = "display:none";
}
}
minWidth = "width:" + this.width + "px;";
minAvatarWidth = "width:" + avatarWidth + "px;";
background = "background-size:" + avatarWidth + "px auto;";
divWidth = minWidth;
divHeight = "min-height:" + avatarWidth + "px;";
responseWidth = "width:" + (this.width - 32) + "px;";
maxDivWidth = "max-width:" + (this.width - 50) + "px;";
scrollerHeight = avatarWidth;
}
if (this.height != null) {
if (typeof this.height === "string") {
this.height = parseInt(this.height);
}
minHeight = "height:" + this.height + "px;";
divHeight = minHeight;
if (this.width != null) {
background = "background-size:" + this.width + "px " + this.height + "px;";
} else {
background = "background-size: auto " + this.height + "px;";
divWidth = "min-width:" + this.height + "px;";
responseWidth = "width:" + (this.height - 16) + "px;";
chatWidth = "width:" + this.height + "px;";
}
} else {
scrollerMinHeight = "height:" + scrollerHeight + "px;";
}
var boxloc = "bottom:10px;right:10px";
if (this.boxLocation == "top-left") {
boxloc = "top:10px;left:10px";
} else if (this.boxLocation == "top-right") {
boxloc = "top:10px;right:10px";
} else if (this.boxLocation == "bottom-left") {
boxloc = "bottom:10px;left:10px";
} else if (this.boxLocation == "bottom-right") {
boxloc = "bottom:10px;right:10px";
}
var locationBottom = 20;
if (this.version < 6.0 || this.prefix != "botplatformchat") {
locationBottom = 2;
}
var boxbarloc = "bottom:" + (locationBottom + this.verticalOffset) + "px;right:" + this.offset + "px";
if (this.boxLocation == "top-left") {
boxbarloc = "top:" + (locationBottom + this.verticalOffset) + "px;left:" + this.offset + "px";
} else if (this.boxLocation == "top-right") {
boxbarloc = "top:" + (locationBottom + this.verticalOffset) + "px;right:" + this.offset + "px";
} else if (this.boxLocation == "bottom-left") {
boxbarloc = "bottom:" + (locationBottom + this.verticalOffset) + "px;left:" + this.offset + "px";
} else if (this.boxLocation == "bottom-right") {
boxbarloc = "bottom:" + (locationBottom + this.verticalOffset) + "px;right:" + this.offset + "px";
}
if (this.version >= 8.5) {
if(!(SDK.isMSIE() || SDK.isEdge())){
this.enableShadowDOM = true;
}
}
var box = document.createElement('div');
this.baseRoot = this.enableShadowDOM ? box.attachShadow({mode: 'open'}) : document;
var html = "";
if (this.css != null) {
html = html + "\n";
}
if (this.buttoncss != null) {
html = html + "\n";
}
html = html + "\n"
+ "
"
+ "
"
+ (this.backlink ? "powered by " + SDK.NAME + "" : "")
+ "" + this.instanceName + ""
+ "";
if (this.showBoxmax) {
html = html + " ";
} else {
html = html + " ";
}
html = html + "
";
if (this.online) {
html = html
+ "
"
+ "
"
+ "
"
+ "
"
+ "
";
}
if (this.chatLog) {
html = html
+ "
"
+ "
"
+ "
"
}
if (this.avatar) {
html = html
+ "
"
+ "
"
+ ""
+ "
"
+ "
"
+ ""
+ "
"
+ "
"
+ ""
+ "
"
+ "
"
+ "
"
+ "
";
}
var urlprefix = this.sdk.credentials.url + "/";
html = html
+ "
"
+ "";
if (this.showChooseLanguage) {
html = html + "";
}
html = html + "";
if (this.allowSpeech) {
html = html
+ "";
}
if (this.allowSpeechRecognition == true || (this.allowSpeechRecognition == null && this.allowSpeech && SDK.isChrome())) {
html = html
+ "";
}
html = html + ""
+ ""
+ ""
+ "";
}
if (this.allowFiles && this.showFileButtons) {
html = html
+ ""
+ "";
}
html = html
+ ""
+ "
";
if (this.enableShadowDOM) {
this.baseRoot.innerHTML = html;
} else {
box.innerHTML = html;
}
SDK.body().appendChild(box);
var self = this;
this.baseRoot.getElementById(this.prefix + "avatarboxclose").addEventListener("click", function() {
self.closePlay();
self.closeBox();
return false;
});
this.closed = false;
}
/**
* Close the embedding div for the play button in the current webpage.
*/
this.closePlay = function() {
if(this.baseRoot.getElementById("sdkplaybutton") != null){
this.baseRoot.getElementById("sdkplaybutton").style.display = "none";
}
}
/**
* Open the embedding div in the current webpage.
*/
this.openBox = function() {
this.baseRoot.getElementById(this.prefix + "avatarbox").style.display = 'inline';
this.speak = true;
this.closed = false;
return false;
}
/**
* Close the embedding div in the current webpage.
*/
this.closeBox = function() {
this.baseRoot.getElementById(this.prefix + "avatarbox").style.display = 'none';
if (SDK.audio != null) {
SDK.audio.pause();
}
if (SDK.currentAudio != null) {
SDK.currentAudio.pause();
}
speechSynthesis.cancel();
this.speak = false;
if (this.onclose != null) {
this.onclose();
}
this.closed = true;
return false;
}
/**
* Update the avatar's image/video/audio from the message response.
*/
this.updateAvatar = function(responseMessage, afterFunction) {
var urlprefix = this.connection.credentials.url + "/";
SDK.updateAvatar(responseMessage, this.speak, urlprefix, this.prefix, null, afterFunction, this.nativeVoice, this.lang, this.nativeVoiceName, this.baseRoot);
};
/**
* Add the message to the avatars message queue.
* The messages will be spoken when processMessages() is called.
*/
this.addMessage = function(message, emote, action, pose) {
var config = new AvatarMessage();
config.message = message;
config.avatar = this.avatar;
if (this.hd != null) {
config.hd = this.hd;
} else if ((this.width != null && this.width > 400) || (this.height != null && this.height > 400)) {
config.hd = true;
}
if (this.format != null) {
config.format = this.format;
}
config.voiceProvider = this.voiceProvider;
if (SDK.bingSpeech) {
config.voiceProvider = "microsoft";
config.speak = true;
this.nativeVoice = false;
} else if (SDK.googleSpeech) {
config.voiceProvider = "google";
config.speak = true;
this.nativeVoice = false;
} else if (SDK.qqSpeech) {
config.voiceProvider = "qq";
config.speak = true;
this.nativeVoice = false;
}
if (this.nativeVoice && SDK.speechSynthesis) {
config.speak = false;
} else {
config.speak = this.speak;
config.voice = this.voice;
config.voiceMod = this.voiceMod;
}
config.emote = emote;
config.action = action;
config.pose = pose;
config.apiKey = this.apiKey;
config.apiEndpoint = this.apiEndpoint;
config.nativeVoiceName = this.nativeVoiceName;
if (this.messages == null) {
this.messages = [];
}
this.messages[this.messages.length] = config;
return false;
};
/**
* Add the message to the avatars message queue.
* The messages will be spoken when runMessages() is called.
*/
this.processMessages = function(pause) {
if (this.messages == null || this.messages.length == 0) {
if (this.ended != null) {
this.ended();
}
return false;
}
if (pause == null) {
pause = 500;
}
var self = this;
var message = this.messages[0];
this.messages = this.messages.splice(1, this.messages.length);
this.connection.avatarMessage(message, function(responseMessage) {
if (responseMessage.speech == null && message.voiceProvider) {
if (message.voiceProvider == "microsoft") {
SDK.showError("Invalid API Key, API Endpoint or voice.", "Error");
} else if (message.voiceProvider == "google") {
SDK.showError("Invalid API key or voice.", "Error");
}
}
self.updateAvatar(responseMessage, function() {
setTimeout(function() {
self.processMessages(pause);
}, pause);
});
});
return false;
}
/**
* Have the avatar speak the message with voice and animation.
* The function will be called at the end of the speech.
*/
this.message = function(message, emote, action, pose, afterFunction) {
var config = new AvatarMessage();
config.message = message;
config.avatar = this.avatar;
if (this.nativeVoice && SDK.speechSynthesis) {
config.speak = false;
} else {
config.speak = this.speak;
config.voice = this.voice;
config.voiceMod = this.voiceMod;
}
config.emote = emote;
config.action = action;
config.pose = pose;
var self = this;
this.connection.avatarMessage(config, function(responseMessage) {
self.updateAvatar(responseMessage, afterFunction);
});
return false;
};
}
/**
* Connection class for a Live Chat, or chatroom connection.
* A live chat connection is different than an SDKConnection as it is asynchronous,
* and uses web sockets for communication.
* @class
* @property channel
* @property user
* @property credentials
* @property listener
* @property keepAlive
* @property onMediaStream
* @property onMediaStreamEnded
* @property nick
* @property channelToken
* @property onNewChannel
* @property nick
*/
function LiveChatConnection() {
this.channel = null;
this.user = null;
this.contactInfo = null;
this.credentials = new Credentials();
this.socket = null;
this.listener = null;
this.keepAlive = true;
this.keepAliveInterval = null;
this.mediaConnection = null;
this.onMediaStream = null;
this.onMediaStreamEnded = null;
this.nick = null;
this.channelToken = null;
this.onNewChannel = null;
this.onMessageCallbacks = {};
/**
* Connect to the live chat server channel.
* Validate the user credentials.
* This call is asynchronous, any error or success with be sent as a separate message to the listener.
*/
this.connect = function(channel, user) {
if (this.credentials == null) {
throw "Mising credentials";
}
this.channel = channel;
this.user = user;
if (this.nick == null && this.user != null) {
this.nick = this.user.user;
}
var host = null;
if (SDK.scheme == "https") {
host = "wss://" + this.credentials.host + this.credentials.app + "/live/chat";
} else {
host = "ws://" + this.credentials.host + this.credentials.app + "/live/chat";
}
if ('WebSocket' in window) {
this.socket = new WebSocket(host);
} else if ('MozWebSocket' in window) {
this.socket = new MozWebSocket(host);
} else {
throw 'Error: WebSocket is not supported by this browser.';
}
this.listener.connection = this;
var self = this;
this.socket.onopen = function () {
if (self.channel != null) {
var appId = self.credentials.applicationId;
if (appId == null) {
appId = '';
}
var connectString = "connect " + self.channel.id;
if (self.user == null) {
connectString = connectString + " " + appId;
} else if (user.token == null) {
connectString = connectString + " " + self.user.user + " " + self.user.password + " " + appId;
} else {
connectString = connectString + " " + self.user.user + " " + self.user.token + " " + appId;
}
if (self.contactInfo != null) {
connectString = connectString + " @info " + self.contactInfo;
}
self.socket.send(connectString);
}
self.setKeepAlive(self.keepAlive);
};
this.socket.onclose = function () {
self.listener.message("Info: Closed");
self.listener.closed();
self.disconnectMedia();
};
this.socket.onmessage = function (message) {
user = "";
data = message.data;
text = data;
index = text.indexOf(':');
if (index != -1) {
user = text.substring(0, index);
data = text.substring(index + 2, text.length);
}
if (user == "Media") {
data = JSON.parse(data);
if (data.sender == self.nick) {
return;
}
if (data.channel != self.channelToken) {
return;
}
if(data.message = "update-users"){
return;
}
if (self.onMessageCallbacks[data.channel]) {
self.onMessageCallbacks[data.channel](data.message);
};
return;
}
if (user == "Online-xml") {
self.listener.updateUsersXML(data);
return;
}
if (user == "Online") {
self.listener.updateUsers(data);
return;
}
if (user == "Channel") {
self.channelToken = data;
if (self.onNewChannel != null) {
self.onNewChannel(data);
}
return;
}
if (user == "Nick") {
if (self.nick == null) {
self.nick = data;
}
return;
}
if (self.keepAlive && user == "Info" && text.includes("pong")) {
return;
}
if (user == "Info") {
self.listener.info(text);
return;
}
if (user == "Error") {
self.listener.error(text);
return;
}
self.listener.message(text);
};
};
/**
* Connect to the active channels media feed (video, audio).
*/
this.connectMedia = function(mediaChannel, shareAudio, shareVideo) {
if (this.mediaConnection != null) {
this.mediaConnection.leave();
}
this.mediaConnection = new RTCMultiConnection(mediaChannel);
this.mediaConnection.socketURL = 'https://rtcmulticonnection.herokuapp.com:443/';
if (this.turnserver != null) {
this.mediaConnection.iceServers.push({
urls: this.turnServer,
credential: this.turnPassword,
username: this.turnUser
});
}
var self = this;
var open = false;
this.mediaConnection.session = {
audio: true,
video: true
};
this.mediaConnection.sdpConstraints.mandatory = {
OfferToReceiveVideo: shareVideo,
OfferToReceiveAudio: shareAudio
};
this.mediaConnection.mediaConstraints = {
audio: shareAudio,
video: shareVideo
};
/*this.mediaConnection.mediaConstraints.audio = {
mandatory: {},
optional: [{
googEchoCancellation: true,
googAutoGainControl: true,
googNoiseSuppression: true,
googHighpassFilter: true,
googTypingNoiseDetection: true,
googAudioMirroring: true
}]
};*/
/*this.mediaConnection.privileges = {
canStopRemoteStream: true,
canMuteRemoteStream: true
};*/
this.mediaConnection.openSignalingChannel = function (config) {
var channel = config.channel || this.channel;
self.onMessageCallbacks[channel] = config.onmessage;
if (config.onopen) {
setTimeout(config.onopen, 1000);
}
// directly returning socket object using "return" statement
return {
send: function (message) {
self.socket.send("Media: " + JSON.stringify({
sender: self.nick,
channel: channel,
message: message
}));
},
channel: channel
};
};
this.mediaConnection.onstream = function(stream) {
if (self.onMediaStream != null) {
self.onMediaStream(stream);
}
};
this.mediaConnection.onstreamended = function(stream) {
if (self.onMediaStreamEnded != null) {
self.onMediaStreamEnded(stream);
}
};
if (this.nick != null) {
this.mediaConnection.userid = "user-"+this.nick;
}
//connection.log = false;
this.mediaConnection.onerror = function(error) {
SDK.error(error);
}
this.mediaConnection.onMediaError = function(error) {
SDK.error(error);
}
this.mediaConnection.connectSocket(function() {
if(!shareVideo && !shareAudio){
self.mediaConnection.dontCaptureUserMedia = true;
}
self.mediaConnection.openOrJoin("botlibreChatRoom");
});
this.mediaConnection.onleave = function(e){
document.getElementById(e.userid).remove();
}
}
/**
* Disconnect from the active channels media feed (video, audio).
*/
this.disconnectMedia = function() {
if (this.mediaConnection != null) {
connection = this.mediaConnection;
connection.getAllParticipants().forEach(function(pid) {
connection.disconnectWith(pid);
});
connection.attachStreams.forEach(function(localStream) {
localStream.stop();
});
this.mediaConnection.closeSocket();
this.mediaConnection = null;
document.getElementById("user-"+user.user).remove();
self = this;
setTimeout(function(){
self.socket.send("Media: " + JSON.stringify({
sender: self.nick,
channel: self.channel,
message: "update-users"
}));
}, 1000);
}
}
/**
* Reset the media feed (audio, video).
*/
this.resetMedia = function(shareAudio, shareVideo) {
streamid = null;
this.mediaConnection.sdpConstraints.mandatory = {
OfferToReceiveVideo: shareVideo,
OfferToReceiveAudio: shareAudio
};
this.mediaConnection.mediaConstraints = {
video: shareVideo,
audio: shareAudio
};
this.mediaConnection.addStream({
video: shareVideo,
audio: shareAudio
});
if(this.mediaConnection.attachStreams.length > 1){
streamid = this.mediaConnection.attachStreams[0].streamid;
}
var connection = this.mediaConnection;
this.mediaConnection.attachStreams.forEach(function(stream){
if(stream.streamid != streamid){
stream.stop();
}
});
}
/**
* Decrease the size of the video element for the userid.
*/
this.shrinkVideo = function(user) {
var streams = this.mediaConnection.streamEvents.selectAll({remote:true, local:true});
for (i = 0; i < streams.length; i++) {
stream = streams[i];
if (stream.userid == user) {
stream.mediaElement.height = stream.mediaElement.height / 1.5;
}
}
};
/**
* Increase the size of the video element for the userid.
*/
this.expandVideo = function(user) {
var streams = this.mediaConnection.streamEvents.selectAll({remote:true, local:true});
for (i = 0; i < streams.length; i++) {
stream = streams[i];
if (stream.userid == user) {
stream.mediaElement.height = stream.mediaElement.height * 1.5;
}
}
};
/**
* Mute the audio for the userid.
*/
this.muteAudio = function(user) {
var streams = this.mediaConnection.streamEvents.selectAll({remote:true, local:true});
for (i = 0; i < streams.length; i++) {
stream = streams[i];
if (stream.userid == user) {
stream.stream.mute({
audio: true
});
}
}
};
/**
* Mute the video for the userid.
*/
this.muteVideo = function(user) {
var streams = this.mediaConnection.streamEvents.selectAll({remote:true, local:true});
for (i = 0; i < streams.length; i++) {
stream = streams[i];
if (stream.userid == user) {
stream.stream.mute({
video: true
});
}
}
};
/**
* Sent a text message to the channel.
* This call is asynchronous, any error or success with be sent as a separate message to the listener.
* Note, the listener will receive its own messages.
*/
this.sendMessage = function(message) {
this.checkSocket();
this.socket.send(message);
};
this.sendAttachment = function(file, resize, form) {
var self = this;
var media = new MediaConfig();
if (this.channel == null) {
this.listener.error("Missing channel property");
return false;
}
media.instance = this.channel.id;
media.name = file.name;
media.type = file.type;
if (!resize && file.size > SDK.MAX_FILE_UPLOAD) {
this.listener.error("File exceeds maximum upload size of " + (SDK.MAX_FILE_UPLOAD / 1000000) + "meg");
} else {
this.sdk.error = function(message) {
self.listener.error(message);
}
this.sdk.createChannelAttachment(media, file, resize, form, function(media) {
var message = "file: " + file.name + " : " + file.type + " : " + self.sdk.fetchLink(media.file);
self.sendMessage(message);
})
}
return false;
};
/**
* Accept a private request.
* This is also used by an operator to accept the top of the waiting queue.
* This can also be used by a user to chat with the channel bot.
* This call is asynchronous, any error or success with be sent as a separate message to the listener.
*/
this.accept = function() {
this.checkSocket();
this.socket.send("accept");
};
/**
* Test the connection.
* A pong message will be returned, this message will not be broadcast to the channel.
* This call is asynchronous, any error or success with be sent as a separate message to the listener.
*/
this.ping = function() {
this.checkSocket();
this.socket.send("ping");
};
/**
* Exit from the current private channel.
* This call is asynchronous, any error or success with be sent as a separate message to the listener.
*/
this.exit = function() {
this.checkSocket();
this.socket.send("exit");
if (SDK.audio != null) {
SDK.audio.pause();
}
if (SDK.currentAudio != null) {
SDK.currentAudio.pause();
}
speechSynthesis.cancel();
};
/**
* Change to spy mode.
* This allows admins to monitor the entire channel.
*/
this.spyMode = function() {
this.checkSocket();
this.socket.send("mode: spy");
};
/**
* Change to normal mode.
*/
this.normalMode = function() {
this.checkSocket();
this.socket.send("mode: normal");
};
/**
* Request a private chat session with a user.
* This call is asynchronous, any error or success with be sent as a separate message to the listener.
*/
this.pvt = function(user) {
this.checkSocket();
this.socket.send("pvt: " + user);
};
/**
* Boot a user from the channel.
* You must be a channel administrator to boot a user.
* This call is asynchronous, any error or success with be sent as a separate message to the listener.
*/
this.boot = function(user) {
this.checkSocket();
this.socket.send("boot: " + user);
};
/**
* Send a private message to a user.
* This call is asynchronous, any error or success with be sent as a separate message to the listener.
*/
this.whisper = function(user, message) {
this.checkSocket();
this.socket.send("whisper:" + user + ": " + message);
};
/**
* Disconnect from the channel.
*/
this.disconnect = function() {
this.setKeepAlive(false);
if (this.socket != null) {
this.socket.disconnect();
}
disconnectMedia();
};
this.checkSocket = function() {
if (this.socket == null) {
throw "Not connected";
}
};
this.toggleKeepAlive = function() {
this.setKeepAlive(!this.keepAlive);
}
this.setKeepAlive = function(keepAlive) {
var self = this;
this.keepAlive = keepAlive;
if (!keepAlive && this.keepAliveInterval != null) {
clearInterval(this.keepAliveInterval);
} else if (keepAlive && this.keepAliveInterval == null) {
this.keepAliveInterval = setInterval(
function() {
self.ping()
},
50000);
}
}
}
/**
* Connection class for a REST service connection.
* The SDK connection gives you access to the Bot Libre services using a REST web API.
*
* The services include:
*
*
User management (account creation, validation)
*
Bot access, chat, and administration
*
Forum access, posting, and administration
*
Live chat access, chat, and administration
*
Script, Graphic, and Domain access, and administration
*
* @class
* @property user
* @property domain
* @property credentials
* @property debug
* @property error
*/
function SDKConnection() {
this.user;
this.domain;
this.credentials = new Credentials();
this.debug = SDK.debug;
this.error = SDK.error;
this.exception;
/**
* Validate the user credentials (password, or token).
* The user details are returned (with a connection token, password removed).
* The user credentials are soted in the connection, and used on subsequent calls.
* An SDKException is thrown if the connect failed.
*/
this.connect = function(config, processor) {
var self = this;
this.fetchUser(config, function(user) {
self.user = user;
processor(user);
});
}
/**
* Connect to the live chat channel and return a LiveChatConnection.
* A LiveChatConnection is separate from an SDKConnection and uses web sockets for
* asynchronous communication.
* The listener will be notified of all messages.
*/
this.openLiveChat = function(channel, listener) {
var connection = new LiveChatConnection();
connection.sdk = this;
connection.credentials = this.credentials;
connection.listener = listener;
connection.connect(channel, this.user);
return connection;
}
/**
* Connect to the domain.
* A domain is an isolated content space.
* Any browse or query request will be specific to the domain's content.
*/
this.switchDomain = function(config, processor) {
var self = this;
this.fetch(config, function(domain) {
self.domain = domain;
processor(domain);
});
}
/**
* Disconnect from the connection.
* An SDKConnection does not keep a live connection, but this resets its connected user and domain.
*/
this.disconnect = function() {
this.user = null;
this.domain = null;
}
/**
* testAnalytic will upload an image to memmory and try to recognize the image.
*/
this.testAnalytic = function(config, file, resize, form, processor, image_size) {
var self = this;
if (!resize && file.size > SDK.MAX_FILE_UPLOAD) {
this.error("File exceeds maximum upload size of " + (SDK.MAX_FILE_UPLOAD / 1000000) + "meg");
} else {
config.addCredentials(this);
if (resize) {
this.POST_IMAGE_SIZED(this.credentials.rest + "/test-analytic", file, form, config.toXML(), function(xml) {
if (xml == null) {
return null;
}
var media = new AnalyticResponse();
media.parseXML(xml);
processor(media);
}, image_size);
} else {
this.POST_FILE(this.credentials.rest + "/test-analytic", form, config.toXML(), function(xml) {
if (xml == null) {
return null;
}
var media = new AnalyticResponse();
media.parseXML(xml);
processor(media);
});
}
}
return false;
};
/**
* testAnalytic will upload an image to memmory and try to recognize the image.
*/
this.testAudioAnalytic = function(config, file, form, processor) {
if (file.size > SDK.MAX_FILE_UPLOAD) {
this.error("File exceeds maximum upload size of " + (SDK.MAX_FILE_UPLOAD / 1000000) + "meg");
} else {
config.addCredentials(this);
this.POST_FILE(this.credentials.rest + "/test-audio-analytic", form, config.toXML(), function(xml) {
if (xml == null) {
return null;
}
var media = new AnalyticAudioResponse();
media.parseXML(xml);
processor(media);
});
}
return false;
};
this.testObjectDetectionAnalytic = function(config, file, resize, form, processor, image_size) {
if (!resize && file.size > SDK.MAX_FILE_UPLOAD) {
this.error("File exceeds maximum upload size of " + (SDK.MAX_FILE_UPLOAD / 1000000) + "meg");
} else {
config.addCredentials(this);
if (resize) {
this.POST_IMAGE_SIZED(this.credentials.rest + "/test-object-detection-analytic", file, form, config.toXML(), function(xml) {
if (xml == null) {
return null;
}
var media = new AnalyticObjectDetectionResponse();
media.parseXML(xml);
processor(media);
}, image_size);
} else {
this.POST_FILE(this.credentials.rest + "/test-object-detection-analytic", form, config.toXML(), function(xml) {
if (xml == null) {
return null;
}
var media = new AnalyticObjectDetectionResponse();
media.parseXML(xml);
processor(media);
});
}
}
return false;
};
this.testNlpAnalytic = function(config, file, form, processor) {
if (file.size > SDK.MAX_FILE_UPLOAD) {
this.error("File exceeds maximum upload size of " + (SDK.MAX_FILE_UPLOAD / 1000000) + "meg");
} else {
config.addCredentials(this);
this.POST_FILE(this.credentials.rest + "/test-nlp-analytic", form, config.toXML(), function(xml) {
if (xml == null) {
return null;
}
var media = new AnalyticNlpResponse();
media.parseXML(xml);
processor(media);
});
}
return false;
}
this.sendAnalyticImage = function(analyticConfig, processor, file, form, image_size) {
if (!(window.File && window.FileReader && window.FileList && window.Blob)) {
alert('The File APIs are not fully supported in this browser.');
return false;
}
this.testAnalytic(analyticConfig, file, true, form, processor, image_size);
};
this.sendObjectDetectionAnalyticImage = function(analyticConfigTest, processor, file, form, image_size) {
if (!(window.File && window.FileReader && window.FileList && window.Blob)) {
alert('The File APIs are not fully supported in this browser.');
return false;
}
this.testObjectDetectionAnalytic(analyticConfigTest, file, true, form, processor, image_size);
};
this.sendAudioAnalytic = function(analyticConfig, processor, file, form) {
if (!(window.File && window.FileReader && window.FileList && window.Blob)) {
alert('The File APIs are not fully supported in this browser.');
return false;
}
this.testAudioAnalytic(analyticConfig, file, form, processor);
};
this.sendNlpAnalytic = function(analyticConfig, processor, file, form) {
if (!(window.File && window.FileReader && window.FileList && window.Blob)) {
alert('The File APIs are not fully supported in this browser.');
return false;
}
this.testNlpAnalytic(analyticConfig, file, form, processor);
};
this.getTestMediaResult = function(config, processor) {
config.addCredentials(this);
this.POST(this.credentials.rest + "/get-test-media-result", config.toXML(), function(xml) {
if(xml == null){
return null;
}
var config = new AnalyticTestMediaResponse();
config.parseXML(xml);
processor(config)
});
}
this.checkTraining = function(config, processor) {
config.addCredentials(this);
this.POST(this.credentials.rest + "/check-training", config.toXML(), function(xml) {
if (xml == null) {
return null;
}
var config = new AnalyticConfig();
config.parseXML(xml);
processor(config);
});
}
this.trainAnalytic = function(config, processor) {
config.addCredentials(this);
this.POST(this.credentials.rest + "/train-analytic", config.toXML(), function(xml) {
if (xml == null) {
return null;
}
var analytic = new AnalyticConfig();
analytic.parseXML(xml);
processor(analytic);
});
}
/**
* processing test media
*/
this.reportMediaAnalytic = function(config, processor) {
config.addCredentials(this);
this.POST(this.credentials.rest + "/report-media-analytic", config.toXML(), function(xml) {
if (xml == null) {
return null;
}
var analytic = new AnalyticConfig();
analytic.parseXML(xml);
processor(analytic);
});
}
this.deleteAnalyticMedia = function(config, done) {
config.addCredentials(this);
this.POST(this.credentials.rest + "/delete-analytic-media", config.toXML(), function(xml) {
return;
});
done();
}
this.deleteAnalyticTestMedia = function(config, done) {
config.addCredentials(this);
this.POST(this.credentials.rest + "/delete-analytic-test-media", config.toXML(), function(xml) {
return;
});
done();
}
this.createAnalyticLabel = function(config) {
config.addCredentials(this);
this.POST(this.credentials.rest + "/create-analytic-label", config.toXML(), function(xml) {
return;
});
}
this.createAnalyticTestMediaLabel = function(config) {
config.addCredentials(this);
this.POST(this.credentials.rest + "/create-analytic-test-media-label", config.toXML(), function(xml) {
return;
});
}
this.deleteAnalyticLabel = function(config) {
config.addCredentials(this);
this.POST(this.credentials.rest + "/delete-analytic-label", config.toXML(), function(xml) {
return;
});
}
this.deleteAnalyticTestMediaLabel = function(config) {
config.addCredentials(this);
this.POST(this.credentials.rest + "/delete-analytic-test-media-label", config.toXML(), function(xml) {
return;
});
}
/**
* Return the list of content for the Analytic media repository
*/
this.getAnalyticMedia = function(config, processor) {
config.addCredentials(this);
this.POST(this.credentials.rest + "/get-analytic-media", config.toXML(), function(xml) {
var instances = [];
if (xml != null) {
for (var index = 0; index < xml.childNodes.length; index++) {
var instance = null;
instance = new AnalyticMediaConfig();
instance.parseXML(xml.childNodes[index]);
instances[instances.length] = (instance);
}
}
processor(instances);
});
}
/**
* Return the list of content for the Analytic test media repository
*/
this.getAnalyticTestMedia = function(config, processor) {
config.addCredentials(this);
this.POST(this.credentials.rest + "/get-analytic-test-media", config.toXML(), function(xml) {
var instances = [];
if (xml != null) {
for (var index = 0; index < xml.childNodes.length; index++) {
var instance = null;
instance = new AnalyticMediaConfig();
instance.parseXML(xml.childNodes[index]);
instances[instances.length] = (instance);
}
}
processor(instances);
});
}
/**
* Fetch the user details for the user credentials.
* A token or password is required to validate the user.
*/
this.fetchUser = function(config, processor) {
config.addCredentials(this);
this.POST(this.credentials.rest + "/check-user", config.toXML(), function(xml) {
if (xml == null) {
return;
}
var user = new UserConfig();
user.parseXML(xml);
processor(user);
});
}
/**
* Move bot's script up.
*/
this.upBotScript = function(config, processor) {
config.addCredentials(this);
this.POST(this.credentials.rest + "/up-bot-script", config.toXML(), function(xml) {
processor();
});
}
/**
* Move bot's script down.
*/
this.downBotScript = function(config, processor) {
config.addCredentials(this);
this.POST(this.credentials.rest + "/down-bot-script", config.toXML(), function(xml) {
processor();
});
}
/**
* Delete bot's script.
*/
this.deleteBotScript = function(config, processor) {
config.addCredentials(this);
this.POST(this.credentials.rest + "/delete-bot-script", config.toXML(), function(xml) {
processor();
});
}
/**
* Save script object's source.
*/
this.saveScriptSource = function(config, processor) {
config.addCredentials(this);
this.POST(this.credentials.rest + "/save-script-source", config.toXML(), function(xml) {
if (processor != null) {
processor();
}
});
}
/**
* Save bot's script source
*/
this.saveBotScriptSource = function(config, processor) {
config.addCredentials(this);
this.POST(this.credentials.rest + "/save-bot-script-source", config.toXML(), function(xml) {
if (xml == null) {
return;
}
var newConfig = new ScriptSourceConfig();
newConfig.parseXML(xml);
if (processor != null) {
processor(newConfig);
}
});
}
/**
* Fetch the user details for the user id.
*/
this.viewUser = function(config, processor) {
config.addCredentials(this);
this.POST(this.credentials.rest + "/view-user", config.toXML(), function(xml) {
if (xml == null) {
return;
}
var user = new UserConfig();
user.parseXML(xml);
processor(user);
});
}
/**
* Fetch the URL for the image from the server.
*/
this.fetchImage = function(image) {
return this.credentials.url + "/" + image;
}
/**
* Fetch the URL for the image from the server.
*/
this.fetchLink = function(image) {
return this.credentials.url + "/" + image;
}
/**
* Fetch the forum post details for the forum post id.
*/
this.fetchForumPost = function(config, processor) {
config.addCredentials(this);
this.POST(this.credentials.rest + "/check-forum-post", config.toXML(), function(xml) {
if (xml == null) {
return;
}
var post = new ForumPostConfig();
post.parseXML(xml);
processor(post);
});
}
/**
* Create a new user.
*/
this.createUser = function(config, processor) {
config.addCredentials(this);
this.POST(this.credentials.rest + "/create-user", config.toXML(), function(xml) {
if (xml == null) {
return null;
}
var user = new UserConfig();
user.parseXML(xml);
this.user = user;
processor(user);
});
}
/**
* Create a new file/image/media attachment for a chat channel.
*/
this.createChannelAttachment = function(config, file, resize, form, processor) {
config.addCredentials(this);
if (resize) {
this.POST_IMAGE(this.credentials.rest + "/create-channel-attachment", file, form, config.toXML(), function(xml) {
if (xml == null) {
return null;
}
var media = new MediaConfig();
media.parseXML(xml);
processor(media);
});
} else {
this.POST_FILE(this.credentials.rest + "/create-channel-attachment", form, config.toXML(), function(xml) {
if (xml == null) {
return null;
}
var media = new MediaConfig();
media.parseXML(xml);
processor(media);
});
}
}
/**
* Create a new file/image/media attachment for a bot.
*/
this.createBotAttachment = function(config, file, resize, form, processor) {
config.addCredentials(this);
if (resize) {
this.POST_IMAGE(this.credentials.rest + "/create-bot-attachment", file, form, config.toXML(), function(xml) {
if (xml == null) {
return null;
}
var media = new MediaConfig();
media.parseXML(xml);
processor(media);
});
} else {
this.POST_FILE(this.credentials.rest + "/create-bot-attachment", form, config.toXML(), function(xml) {
if (xml == null) {
return null;
}
var media = new MediaConfig();
media.parseXML(xml);
processor(media);
});
}
}
/**
* Create a new file/image/media attachment for a bot.
*/
this.createAudioAttachment = function(config, file, form, processor) {
config.addCredentials(this);
this.POST_FILE(this.credentials.rest + "/create-bot-attachment", form, config.toXML(), function(xml) {
if (xml == null) {
return null;
}
var media = new MediaConfig();
media.parseXML(xml);
processor(media);
});
}
/**
* Create a new file/image/media attachment for an issue tracker.
*/
this.createIssueTrackerAttachment = function(config, file, resize, form, processor) {
config.addCredentials(this);
if (resize) {
this.POST_IMAGE(this.credentials.rest + "/create-issuetracker-attachment", file, form, config.toXML(), function(xml) {
if (xml == null) {
return null;
}
var media = new MediaConfig();
media.parseXML(xml);
processor(media);
});
} else {
this.POST_FILE(this.credentials.rest + "/create-issuetracker-attachment", form, config.toXML(), function(xml) {
if (xml == null) {
return null;
}
var media = new MediaConfig();
media.parseXML(xml);
processor(media);
});
}
}
/**
* Create a new file/image/media attachment for an issue tracker and insert the http link into the textarea.
*/
this.uploadIssueTrackerAttachment = function(forum, resize, processor) {
if (!(window.File && window.FileReader && window.FileList && window.Blob)) {
this.error('The File APIs are not fully supported in this browser.');
return false;
}
var form = document.createElement("form");
form.enctype = "multipart/form-data";
form.method = "post";
form.name = "fileinfo";
var fileInput = document.createElement("input");
var self = this;
fileInput.name = "file";
fileInput.type = "file";
form.appendChild(fileInput);
fileInput.onchange = function() {
var file = fileInput.files[0];
self.uploadIssueTrackerFile(file, forum, resize, form, processor);
}
fileInput.click();
};
/**
* Create a new file/image/media attachment for an issue tracker.
*/
this.uploadIssueTrackerFile = function(file, forum, resize, form, processor) {
var self = this;
var media = new MediaConfig();
media.instance = forum;
media.name = file.name;
media.type = file.type;
if (!resize && file.size > SDK.MAX_FILE_UPLOAD) {
this.error("File exceeds maximum upload size of " + (SDK.MAX_FILE_UPLOAD / 1000000) + "meg");
} else {
this.createIssueTrackerAttachment(media, file, resize, form, function(media) {
var link = self.fetchLink(media.file);
if (processor != null) {
processor(link, file.name);
}
})
}
};
/**
* Create a new file/image/media attachment for a forum.
*/
this.createForumAttachment = function(config, file, resize, form, processor) {
config.addCredentials(this);
if (resize) {
this.POST_IMAGE(this.credentials.rest + "/create-forum-attachment", file, form, config.toXML(), function(xml) {
if (xml == null) {
return null;
}
var media = new MediaConfig();
media.parseXML(xml);
processor(media);
});
} else {
this.POST_FILE(this.credentials.rest + "/create-forum-attachment", form, config.toXML(), function(xml) {
if (xml == null) {
return null;
}
var media = new MediaConfig();
media.parseXML(xml);
processor(media);
});
}
};
/**
* Create a new file/image/media attachment for a bot.
*/
this.createBotAttachment = function(config, file, resize, form, processor) {
config.addCredentials(this);
if (resize) {
this.POST_IMAGE(this.credentials.rest + "/create-bot-attachment", file, form, config.toXML(), function(xml) {
if (xml == null) {
return null;
}
var media = new MediaConfig();
media.parseXML(xml);
processor(media);
});
} else {
this.POST_FILE(this.credentials.rest + "/create-bot-attachment", form, config.toXML(), function(xml) {
if (xml == null) {
return null;
}
var media = new MediaConfig();
media.parseXML(xml);
processor(media);
});
}
};
/**
* Create a new file/image/media attachment for a bot and insert the http link into the textarea.
*/
this.uploadBotAttachment = function(bot, resize, processor) {
if (!(window.File && window.FileReader && window.FileList && window.Blob)) {
this.error('The File APIs are not fully supported in this browser.');
return false;
}
var form = document.createElement("form");
form.enctype = "multipart/form-data";
form.method = "post";
form.name = "fileinfo";
var fileInput = document.createElement("input");
var self = this;
fileInput.name = "file";
fileInput.type = "file";
form.appendChild(fileInput);
fileInput.onchange = function() {
var file = fileInput.files[0];
self.uploadBotFile(file, bot, resize, form, processor);
}
fileInput.click();
};
/**
* Create a new file/image/media attachment for a forum and insert the http link into the textarea.
*/
this.uploadForumAttachment = function(forum, resize, processor) {
if (!(window.File && window.FileReader && window.FileList && window.Blob)) {
this.error('The File APIs are not fully supported in this browser.');
return false;
}
var form = document.createElement("form");
form.enctype = "multipart/form-data";
form.method = "post";
form.name = "fileinfo";
var fileInput = document.createElement("input");
var self = this;
fileInput.name = "file";
fileInput.type = "file";
form.appendChild(fileInput);
fileInput.onchange = function() {
var file = fileInput.files[0];
self.uploadForumFile(file, forum, resize, form, processor);
}
fileInput.click();
};
/**
* Create a new file/image/media attachment for a bot.
*/
this.uploadBotFile = function(file, bot, resize, form, processor) {
var self = this;
var media = new MediaConfig();
media.instance = bot;
media.name = file.name;
media.type = file.type;
if (!resize && file.size > SDK.MAX_FILE_UPLOAD) {
this.error("File exceeds maximum upload size of " + (SDK.MAX_FILE_UPLOAD / 1000000) + "meg");
} else {
this.createBotAttachment(media, file, resize, form, function(media) {
var link = self.fetchLink(media.file);
if (processor != null) {
processor(link, file.name);
}
})
}
};
/**
* Create a new file/image/media attachment for a forum.
*/
this.uploadForumFile = function(file, forum, resize, form, processor) {
var self = this;
var media = new MediaConfig();
media.instance = forum;
media.name = file.name;
media.type = file.type;
if (!resize && file.size > SDK.MAX_FILE_UPLOAD) {
this.error("File exceeds maximum upload size of " + (SDK.MAX_FILE_UPLOAD / 1000000) + "meg");
} else {
this.createForumAttachment(media, file, resize, form, function(media) {
var link = self.fetchLink(media.file);
if (processor != null) {
processor(link, file.name);
}
})
}
};
/**
* Create a new avatar media from the video/audio/image data.
* This returns the medias mediaId.
*/
this.createAvatarMedia = function(config, file, form, processor) {
config.addCredentials(this);
this.POST_FILE(this.credentials.rest + "/create-avatar-media", form, config.toXML(), function(xml) {
processor();
});
}
/**
* Save a avatar media.
* This save the media meta-data.
*/
this.saveAvatarMedia = function(config, processor) {
config.addCredentials(this);
this.POST(this.credentials.rest + "/save-avatar-media", config.toXML(), function(xml) {
processor();
});
}
/**
* Return the avatar's media.
*/
this.getAvatarMedia = function(config, processor) {
config.addCredentials(this);
this.POST(this.credentials.rest + "/get-avatar-media", config.toXML(), function(xml) {
var instances = [];
if (xml != null) {
for (var index = 0; index < xml.childNodes.length; index++) {
var instance = null;
instance = new AvatarMediaConfig();
instance.parseXML(xml.childNodes[index]);
instances[instances.length] = (instance);
}
}
processor(instances);
});
}
/**
* Create a new forum post.
* You must set the forum id for the post.
*/
this.createForumPost = function(config, processor) {
config.addCredentials(this);
var xml = POST(this.credentials.rest + "/create-forum-post", config.toXML(), function(xml) {
if (xml == null) {
return null;
}
var post = new ForumPostConfig();
post.parseXML(xml);
processor(post);
});
}
/**
* Create a reply to a forum post.
* You must set the parent id for the post replying to.
*/
this.createReply = function(config, processor) {
config.addCredentials(this);
var xml = POST(this.credentials.rest + "/create-reply", config.toXML(), function(xml) {
if (xml == null) {
return null;
}
var reply = new ForumPostConfig();
reply.parseXML(xml);
processor(reply);
});
}
/**
* Fetch the content details from the server.
* The id or name and domain of the object must be set.
*/
this.fetch = function(config, processor) {
config.addCredentials(this);
this.POST(this.credentials.rest + "/check-" + config.type, config.toXML(), function(xml) {
if (xml == null) {
return null;
}
var config2 = new config.constructor();
config2.parseXML(xml);
processor(config2)
});
}
/**
* Create the content.
*/
this.create = function(config, processor) {
config.addCredentials(this);
this.POST(this.credentials.rest + "/create-" + config.type, config.toXML(), function(xml) {
if (xml == null) {
return null;
}
var config2 = new config.constructor();
config2.parseXML(xml);
processor(config2)
});
}
/**
* Update the content of the graphic.
*/
this.updateGraphic = function(config) {
config.addCredentials(this);
this.POST(this.credentials.rest + "/update-graphic", config.toXML(), function(xml) {
return;
});
}
/**
* Update the forum post.
*/
this.updateForumPost = function(config, processor) {
config.addCredentials(this);
this.POST(this.credentials.rest + "/update-forum-post", config.toXML(), function(xml) {
if (xml == null) {
return null;
}
var config = new ForumPostConfig();
config.parseXML(xml);
processor(config);
});
}
/**
* Update the user details.
* The password must be passed to allow the update.
*/
this.updateUser = function(config) {
config.addCredentials(this);
this.POST(this.credentials.rest + "/update-user", config.toXML(), function(xml) {
return;
});
}
/**
* Permanently delete the forum post with the id.
*/
this.deleteForumPost = function(config) {
config.addCredentials(this);
this.POST(this.credentials.rest + "/delete-forum-post", config.toXML(), function(xml) {
return;
});
}
/**
* Flag the content as offensive, a reason is required.
*/
this.flag = function(config) {
config.addCredentials(this);
this.POST(this.credentials.rest + "/flag-" + config.getType(), config.toXML(), function(xml) {
return;
});
}
/**
* Flag the forum post as offensive, a reason is required.
*/
this.flagForumPost = function(config) {
config.addCredentials(this);
this.POST(this.credentials.rest + "/flag-forum-post", config.toXML(), function(xml) {
return;
});
}
/**
* Flag the user post as offensive, a reason is required.
*/
this.flagUser = function(config) {
config.addCredentials(this);
this.POST(this.credentials.rest + "/flag-user", config.toXML(), function(xml) {
return;
});
}
/**
* Process the bot chat message and return the bot's response.
* The ChatConfig should contain the conversation id if part of a conversation.
* If a new conversation the conversation id is returned in the response.
*/
this.chat = function(config, processor) {
config.addCredentials(this);
this.POST(this.credentials.rest + "/chat", config.toXML(), function(xml) {
if (xml == null) {
return null;
}
var responseMessage = new ChatResponse();
responseMessage.parseXML(xml);
processor(responseMessage);
});
}
/**
* Process the bot command message and return the bot's response.
* The CommandConfig should contain the conversation id if part of a conversation.
* If a new conversation the conversation id is returned in the response.
*/
this.command = function(config, processor) {
config.addCredentials(this);
this.POST(this.credentials.rest + "/command", config.toXML(), function(xml) {
if (xml == null) {
return null;
}
var responseMessage = new ChatResponse();
responseMessage.parseXML(xml);
processor(responseMessage);
});
}
/**
* Process the avatar message and return the avatar's response.
*/
this.avatarMessage = function(config, processor) {
config.addCredentials(this);
this.POST(this.credentials.rest + "/avatar-message", config.toXML(), function(xml) {
if (xml == null) {
return null;
}
var responseMessage = new ChatResponse();
responseMessage.parseXML(xml);
processor(responseMessage);
});
}
/**
*
*/
this.userAdmin = function(config, processor) {
config.addCredentials(this);
this.POST(this.credentials.rest + "/user-admin", config.toXML(), function(xml) {
processor();
});
}
/**
*
*/
this.userFriendship = function(config, processor) {
config.addCredentials(this);
this.POST(this.credentials.rest + "/user-friendship", config.toXML(), function(xml) {
if (xml != null) {
let userConfig = new UserConfig();
userConfig.parseXML(xml);
processor(userConfig);
} else {
processor();
}
});
}
/**
* Return a chat response generated using the user's avatar and voice.
*/
this.userAvatarMessage = function(config, processor) {
config.addCredentials(this);
this.POST(this.credentials.rest + "/user-avatar-message", config.toXML(), function(xml) {
if (xml != null) {
let chatResponseConfig = new ChatResponse();
chatResponseConfig.parseXML(xml);
processor(chatResponseConfig);
} else {
processor();
}
});
}
/**
* Function polls new user messages
*/
this.pollUserToUserMessages = function(config, processor) {
config.addCredentials(this);
this.POST(this.credentials.rest + "/check-user-new-messages", config.toXML(), function(xml) {
if (xml != null) {
var userMessageConfig = new UserMessageConfig();
userMessageConfig.parseXML(xml);
processor(userMessageConfig);
} else {
processor();
}
});
}
/**
* Function creates new user message
*/
this.createUserMessage = function(config, processor) {
config.addCredentials(this);
this.POST(this.credentials.rest + "/create-user-message", config.toXML(), function(xml) {
if (xml != null) {
var userMessageConfig = new UserMessageConfig();
userMessageConfig.parseXML(xml);
processor(userMessageConfig);
} else {
processor();
}
});
}
/**
* Return the list of user details for the comma separated values list of user ids.
*/
this.fetchAllUsers = function(usersCSV, processor) {
var config = new UserConfig();
config.user = usersCSV;
config.addCredentials(this);
this.POST(this.credentials.rest + "/get-users", config.toXML(), function(xml) {
var users = [];
if (xml != null) {
for (var index = 0; index < xml.childNodes.length; index++) {
var child = xml.childNodes[index];
var userConfig = new UserConfig();
userConfig.parseXML(child);
users[user.length] = userConfig;
}
}
processor(users);
});
}
/**
* Return the list of forum posts for the forum browse criteria.
*/
this.fetchPosts = function(config, processor) {
config.addCredentials(this);
var xml = this.POST(this.credentials.rest + "/get-forum-posts", config.toXML(), function(xml) {
var instances = [];
if (xml != null) {
for (var index = 0; index < xml.childNodes.length; index++) {
var child = xml.childNodes[index];
var post = new ForumPostConfig();
post.parseXML(child);
instances[instances.length] = post;
}
}
processor(instances);
});
}
/**
* Return the list of categories for the type, and domain.
*/
this.fetchCategories = function(config, processor) {
config.addCredentials(this);
var xml = this.POST(this.credentials.rest + "/get-categories", config.toXML(), function(xml) {
var categories = [];
categories[0] = "";
if (xml != null) {
for (var index = 0; index < xml.childNodes.length; index++) {
categories[categories.length] = (xml.childNodes[index].getAttribute("name"));
}
}
processor(categories);
});
}
/**
* Return the list of tags for the type, and domain.
*/
this.fetchTags = function(config, processor) {
config.addCredentials(this);
var xml = this.POST(this.credentials.rest + "/get-tags", config.toXML(), function(xml) {
var tags = [];
tags[0] = "";
if (xml != null) {
for (var index = 0; index < xml.childNodes.length; index++) {
tags[tags.length] = (xml.childNodes[index].getAttribute("name"));
}
}
processor(tags);
});
}
/**
* Return the users for the content.
*/
this.fetchUsers = function(config, processor) {
config.addCredentials(this);
var xml = this.POST(this.credentials.rest + "/get-" + config.getType() + "-users", config.toXML(), function(xml) {
var users = [];
if (xml != null) {
for (var index = 0; index < xml.childNodes.length; index++) {
var user = new UserConfig();
user.parseXML(xml.childNodes[index]);
users[users.length] = (user.user);
}
}
processor(users);
});
}
/**
* Initialize the bot's avatar for a chat session.
* This can be done before processing the first message for a quick response.
* @deprecated replaced by initChat()
*/
this.initAvatar = function(config, processor) {
config.addCredentials(this);
this.POST(this.credentials.rest + "/init-avatar", config.toXML(), function(xml) {
if (xml == null) {
return;
}
var response = new ChatResponse();
response.parseXML(xml);
processor(response);
});
}
/**
* Initialize the bot's avatar for a chat session.
* This can be done before processing the first message for a quick response.
*/
this.initChat = function(config, processor) {
config.addCredentials(this);
this.POST(this.credentials.rest + "/init-chat", config.toXML(), function(xml) {
if (xml == null) {
return;
}
var response = new ChatResponse();
response.parseXML(xml);
processor(response);
});
}
/**
* Return the conversation's chat settings.
*/
this.chatSettings = function(config, processor) {
config.addCredentials(this);
this.POST(this.credentials.rest + "/chat-settings", config.toXML(), function(xml) {
if (xml == null) {
return;
}
var settings = new ChatSettings();
settings.parseXML(xml);
processor(settings);
});
}
/**
* Update the bot's avatar.
*/
this.saveBotAvatar = function(config, processor) {
config.addCredentials(this);
this.POST(this.credentials.rest + "/save-bot-avatar", config.toXML(), function(xml) {
if (processor != null) {
processor();
}
});
}
/**
* Update the bot's voice.
*/
this.saveBotVoice = function(config, processor) {
config.addCredentials(this);
this.POST(this.credentials.rest + "/save-voice", config.toXML(), function(xml) {
if (processor != null) {
processor();
}
});
}
/**
* Add or remove a response for a bot.
*/
this.trainInstance = function(config, processor) {
config.addCredentials(this);
this.POST(this.credentials.rest + "/train-instance", config.toXML(), function(xml) {
if (processor != null) {
processor();
}
});
}
/**
* Add the question/response to bot's responses.
*/
this.addQuestionResponse = function(config, processor) {
config.addCredentials(this);
this.POST(this.credentials.rest + "/save-response", config.toXML(), function(xml) {
if (xml == null) {
return;
}
var responseConfig = new ResponseConfig();
responseConfig.parseXML(xml);
processor(responseConfig);
});
}
/**
* Delete the bot's question/response.
*/
this.deleteQuestionResponse = function(config, processor) {
config.addCredentials(this);
this.POST(this.credentials.rest + "/delete-response", config.toXML(), function(xml) {
if (processor != null) {
processor();
}
});
}
/**
* Return the bot's responses.
* Takes a ResponseSearchConfig.
*/
this.getQuestionResponses = function(config, processor) {
config.addCredentials(this);
this.POST(this.credentials.rest + "/get-responses", config.toXML(), function(xml) {
var instances = [];
if (xml != null) {
for (var index = 0; index < xml.childNodes.length; index++) {
var instance = null;
instance = new ResponseConfig();
instance.parseXML(xml.childNodes[index]);
instances[instances.length] = (instance);
}
}
processor(instances);
});
}
/**
* Return the bot's response matching the ResponseConfig object.
*/
this.getQuestionResponse = function(config, processor) {
config.addCredentials(this);
this.POST(this.credentials.rest + "/get-response", config.toXML(), function(xml) {
if (xml == null) {
return;
}
var response = new ResponseConfig();
response.parseXML(xml);
processor(response);
});
}
/**
* Return the bot's voice configuration.
*/
this.fetchVoice = function(config, processor) {
config.addCredentials(this);
this.POST(this.credentials.rest + "/get-voice", config.toXML(), function(xml) {
if (xml == null) {
return;
}
var voice = new VoiceConfig();
voice.parseXML(xml);
processor(voice);
});
}
/**
* Return the list of content for the browse criteria.
* The type defines the content type (one of Bot, Forum, Channel, Domain).
*/
this.browse = function(config, processor) {
config.addCredentials(this);
var type = "";
if (config.type == "Bot") {
type = "/get-instances";
} else if (config.type == "Forum") {
type = "/get-forums";
} else if (config.type == "Channel") {
type = "/get-channels";
} else if (config.type == "Domain") {
type = "/get-domains";
} else if (config.type == "Graphic") {
type = "/get-graphics";
} else if (config.type == "Avatar") {
type = "/get-avatars";
} else if (config.type == "Script") {
type = "/get-scripts";
} else if (config.type == "Analytic") {
type = "/get-analytics";
}
this.POST(this.credentials.rest + type, config.toXML(), function(xml) {
var instances = [];
if (xml != null) {
for (var index = 0; index < xml.childNodes.length; index++) {
var instance = null;
if (config.type == "Bot") {
instance = new InstanceConfig();
} else if (config.type == "Forum") {
instance = new ForumConfig();
} else if (config.type == "Channel") {
instance = new ChannelConfig();
} else if (config.type == "Domain") {
instance = new DomainConfig();
} else if (config.type == "Avatar") {
instance = new AvatarConfig();
} else if (config.type == "Script") {
instance = new ScriptConfig();
} else if (config.type == "Analytic") {
instance = new AnalyticConfig();
} else if (config.type == "Graphic") {
instance = new GraphicConfig();
}
instance.parseXML(xml.childNodes[index]);
instances[instances.length] = (instance);
}
}
processor(instances);
});
}
this.GET = function(url, processor) {
if (this.debug) {
console.log("GET: " + url);
}
var xml = null;
var request = new XMLHttpRequest();
var debug = this.debug;
var self = this;
request.onreadystatechange = function() {
if (request.readyState != 4) return;
if (request.status != 200) {
console.log('Error: SDK GET web request failed');
if (debug) {
console.log(request.statusText);
console.log(request.responseText);
console.log(request.responseXML);
}
if (request.statusText != null && request.responseText != null && request.responseText.indexOf("") != -1) {
self.error(request.statusText);
} else {
self.error(request.responseText);
}
return;
}
if (request.responseXML == null) {
processor();
} else {
processor(request.responseXML.childNodes[0]);
}
}
request.open('GET', url, true);
request.send();
}
this.POST = function(url, xml, processor) {
if (this.debug) {
console.log("POST: " + url);
console.log("XML: " + xml);
}
var request = new XMLHttpRequest();
var debug = this.debug;
var self = this;
request.onreadystatechange = function() {
if (debug) {
console.log(request.readyState);
console.log(request.status);
console.log(request.statusText);
console.log(request.responseText);
console.log(request.responseXML);
}
if (request.readyState != 4) return;
if (request.status != 200 && request.status != 204) {
console.log('Error: SDK POST web request failed');
if (debug) {
console.log(request.statusText);
console.log(request.responseText);
console.log(request.responseXML);
}
if (request.statusText != null && request.responseText != null && request.responseText.indexOf("") != -1) {
self.error(request.statusText);
} else {
self.error(request.responseText);
}
return;
}
if (request.responseXML == null) {
processor();
} else {
processor(request.responseXML.childNodes[0]);
}
};
request.open('POST', url, true);
request.setRequestHeader("Content-Type", "application/xml");
request.send(xml);
}
this.POST_FILE = function(url, form, xml, processor) {
if (this.debug) {
console.log("POST FILE: " + url);
console.log("FORM: " + form);
console.log("XML: " + xml);
}
var request = new XMLHttpRequest();
var formData = new FormData(form);
formData.append("xml", xml);
var debug = this.debug;
var self = this;
request.onreadystatechange = function() {
if (debug) {
console.log(request.readyState);
console.log(request.status);
console.log(request.statusText);
console.log(request.responseText);
console.log(request.responseXML);
}
if (request.readyState != 4) return;
if (request.status != 200 && request.status != 204) {
console.log('Error: SDK POST web request failed');
if (debug) {
console.log(request.statusText);
console.log(request.responseText);
console.log(request.responseXML);
}
if (request.statusText != null && request.responseText != null && request.responseText.indexOf("") != -1) {
self.error(request.statusText);
} else {
self.error(request.responseText);
}
return;
}
if (request.responseXML == null) {
processor();
} else {
processor(request.responseXML.childNodes[0]);
}
};
request.open('POST', url, true);
//request.setRequestHeader("Content-Type", "multipart/form-data");
request.send(formData);
}
this.POST_IMAGE_SIZED = function(url, file, form, xml, processor, image_size) {
var self = this;
var debug = this.debug;
var reader = new FileReader();
if (this.debug) {
console.log("POST FILE: " + url);
console.log("FORM: " + form);
console.log("XML: " + xml);
}
reader.onloadend = function() {
var tempImg = new Image();
tempImg.src = reader.result;
tempImg.onload = function() {
var MAX_WIDTH = image_size;
var MAX_HEIGHT = image_size;
var tempW = tempImg.width;
var tempH = tempImg.height;
if (tempW > tempH) {
if (tempW > MAX_WIDTH) {
tempH *= MAX_WIDTH / tempW;
tempW = MAX_WIDTH;
}
} else {
if (tempH > MAX_HEIGHT) {
tempW *= MAX_HEIGHT / tempH;
tempH = MAX_HEIGHT;
}
}
var canvas = document.createElement('canvas');
canvas.width = tempW;
canvas.height = tempH;
var ctx = canvas.getContext("2d");
ctx.fillStyle = '#fff';
ctx.fillRect(0, 0, canvas.width, canvas.height);
ctx.drawImage(this, 0, 0, tempW, tempH);
var dataUrl = canvas.toDataURL('image/jpeg');
var blob = SDK.dataURLToBlob(dataUrl);
var request = new XMLHttpRequest();
var formData = new FormData();
formData.append("xml", xml);
formData.append('file', blob, file.name);
request.onreadystatechange = function() {
if (debug) {
console.log(request.readyState);
console.log(request.status);
console.log(request.statusText);
console.log(request.responseText);
console.log(request.responseXML);
}
if (request.readyState != 4) return;
if (request.status != 200 && request.status != 204) {
console.log('Error: SDK POST web request failed');
if (debug) {
console.log(request.statusText);
console.log(request.responseText);
console.log(request.responseXML);
}
if (request.statusText != null && request.responseText != null && request.responseText.indexOf("") != -1) {
self.error(request.statusText);
} else {
self.error(request.responseText);
}
return;
}
if (request.responseXML == null) {
processor();
} else {
processor(request.responseXML.childNodes[0]);
}
};
request.open('POST', url, true);
//request.setRequestHeader("Content-Type", "multipart/form-data");
request.send(formData);
}
}
reader.readAsDataURL(file);
}
this.POST_IMAGE = function(url, file, form, xml, processor) {
var self = this;
var debug = this.debug;
var reader = new FileReader();
reader.onloadend = function() {
var tempImg = new Image();
tempImg.src = reader.result;
tempImg.onload = function() {
var MAX_WIDTH = 600;
var MAX_HEIGHT = 600;
var tempW = tempImg.width;
var tempH = tempImg.height;
if (tempW > tempH) {
if (tempW > MAX_WIDTH) {
tempH *= MAX_WIDTH / tempW;
tempW = MAX_WIDTH;
}
} else {
if (tempH > MAX_HEIGHT) {
tempW *= MAX_HEIGHT / tempH;
tempH = MAX_HEIGHT;
}
}
var canvas = document.createElement('canvas');
canvas.width = tempW;
canvas.height = tempH;
var ctx = canvas.getContext("2d");
ctx.fillStyle = '#fff';
ctx.fillRect(0, 0, canvas.width, canvas.height);
ctx.drawImage(this, 0, 0, tempW, tempH);
var dataUrl = canvas.toDataURL('image/jpeg');
var blob = SDK.dataURLToBlob(dataUrl);
var request = new XMLHttpRequest();
var formData = new FormData();
formData.append("xml", xml);
formData.append('file', blob, file.name);
request.onreadystatechange = function() {
if (debug) {
console.log(request.readyState);
console.log(request.status);
console.log(request.statusText);
console.log(request.responseText);
console.log(request.responseXML);
}
if (request.readyState != 4) return;
if (request.status != 200 && request.status != 204) {
console.log('Error: SDK POST web request failed');
if (debug) {
console.log(request.statusText);
console.log(request.responseText);
console.log(request.responseXML);
}
if (request.statusText != null && request.responseText != null && request.responseText.indexOf("") != -1) {
self.error(request.statusText);
} else {
self.error(request.responseText);
}
return;
}
if (request.responseXML == null) {
processor();
} else {
processor(request.responseXML.childNodes[0]);
}
};
request.open('POST', url, true);
//request.setRequestHeader("Content-Type", "multipart/form-data");
request.send(formData);
}
}
reader.readAsDataURL(file);
}
}
/**
* Abstract root class for all web API message objects.
* Defines the required application id, and common fields.
* @class
* @property application
* @property domain
* @property user
* @property token
* @property instance
* @property type
*/
function Config() {
/** The application ID. This is require to authenticate the API usage. You can obtain your application ID from your user page. */
this.application;
/** Optional domain id, if object is not on the server's default domain. */
this.domain;
/** User ID, required for content creation, secure content access, or to identify the user. */
this.user;
/** User's access token, returned from connect web API, can be used in place of password in subsequent calls, and stored in a cookie. The user's password should never be stored. */
this.token;
/** The id or name of the bot or content instance to access. */
this.instance;
/** Type of instance to access, ("Bot", "Forum", "Channel", "Domain") */
this.type;
this.addCredentials = function(connection) {
this.application = connection.credentials.applicationId;
if (connection.user != null) {
this.user = connection.user.user;
this.token = connection.user.token;
}
if (connection.domain != null) {
this.domain = connection.domain.id;
}
}
this.writeCredentials = function(xml) {
if (this.user != null && this.user.length > 0) {
xml = xml + (" user=\"" + this.user + "\"");
}
if (this.token != null && this.token.length > 0) {
xml = xml + (" token=\"" + this.token + "\"");
}
if (this.type != null && this.type.length > 0) {
xml = xml + (" type=\"" + this.type + "\"");
}
if (this.instance != null && this.instance.length > 0) {
xml = xml + (" instance=\"" + this.instance + "\"");
}
if (this.application != null && this.application.length > 0) {
xml = xml + (" application=\"" + this.application + "\"");
}
if (this.domain != null && this.domain.length > 0) {
xml = xml + (" domain=\"" + this.domain + "\"");
}
return xml;
}
}
/**
* This object models a user.
* It can be used from a chat UI, or with the Libre Web API.
* It can convert itself to/from XML for web API usage.
* This can be used to connect, create, edit, or browse a user instance.
* @class
* @property password
* @property newPassword
* @property hint
* @property name
* @property showName
* @property email
* @property website
* @property bio
* @property over18
* @property avatar
* @property connects
* @property bots
* @property posts
* @property messages
* @property joined
* @property lastConnect
*/
function UserConfig() {
/** Password, require to connect a user, or create a user. */
this.password;
/** New password for editting a user's password (password is old password). */
this.newPassword;
/** Optional password hint, in case password is forgotten. */
this.hint;
/** Optional real name of the user. */
this.name;
/** The real name can be hidden from other users. */
this.showName;
/** Email, required for message notification, and to reset password. */
this.email;
/** Optional user's website. */
this.website;
/** Optional user's bio. */
this.bio;
this.over18;
/** Read-only, server local URL for user's avatar image. */
this.avatar;
this.avatarThumb;
/** Read-only, total user connects. */
this.connects;
/** Read-only, total bots created. */
this.bots;
/** Read-only, total forum posts. */
this.posts;
/** Read-only, total chat messages. */
this.messages;
/** Read-only, date user joined. */
this.joined;
/** Read-only, date of user's last connect. */
this.lastConnect;
this.addCredentials = function(connection) {
this.application = connection.credentials.applicationId;
if (connection.domain != null) {
this.domain = connection.domain.id;
}
}
this.parseXML = function(element) {
this.user = element.getAttribute("user");
this.name = element.getAttribute("name");
this.showName = element.getAttribute("showName") == "true";
this.token = element.getAttribute("token");
this.email = element.getAttribute("email");
this.hint = element.getAttribute("hint");
this.website = element.getAttribute("website");
this.connects = element.getAttribute("connects");
this.bots = element.getAttribute("bots");
this.posts = element.getAttribute("posts");
this.messages = element.getAttribute("messages");
this.joined = element.getAttribute("joined");
this.lastConnect = element.getAttribute("lastConnect");
var node = element.getElementsByTagName("bio")[0];
if (node != null) {
this.bio = SDK.innerHTML(node);
}
node = element.getElementsByTagName("avatar")[0];
if (node != null) {
this.avatar = SDK.innerHTML(node);
}
}
this.toXML = function() {
var xml = "");
if (this.bio != null) {
xml = xml + ("");
xml = xml + (SDK.escapeHTML(this.bio));
xml = xml + ("");
}
xml = xml + ("");
return xml;
}
}
UserConfig.prototype = new Config();
UserConfig.prototype.constructor = UserConfig;
UserConfig.constructor = UserConfig;
/**
* This object models a user message.
* It can be used from a messages UI, or with the Libre Web API.
* It can convert itself to/from XML for web API usage.
* This is used to create new user message instance.
* @class
*/
function UserMessageConfig() {
this.id;
this.creationDate;
this.owner;
this.creator;
this.target;
this.parent;
this.avatar;
this.page;
this.pageSize;
this.resultsSize;
this.subject;
this.message;
this.addCredentials = function(connection) {
this.user = connection.user.user;
this.token = connection.user.token;
this.application = connection.credentials.applicationId;
if (connection.domain != null) {
this.domain = connection.domain.id;
}
}
this.parseXML = function(element) {
var userMessageNode = element.getElementsByTagName("user-message")[0];
if (userMessageNode != null) {
this.id = userMessageNode.getAttribute("id");
this.creationDate = userMessageNode.getAttribute("creationDate");
this.owner = userMessageNode.getAttribute("owner");
this.creator = userMessageNode.getAttribute("creator");
this.target = userMessageNode.getAttribute("target");
this.parent = userMessageNode.getAttribute("parent");
this.avatar = userMessageNode.getAttribute("avatar");
this.page = userMessageNode.getAttribute("page");
this.pageSize = userMessageNode.getAttribute("pageSize");
this.resultsSize = userMessageNode.getAttribute("resultsSize");
}
var subjectNode = element.getElementsByTagName("subject")[0];
if (subjectNode != null) {
this.subject = SDK.innerHTML(subjectNode);
}
var messageNode = element.getElementsByTagName("message")[0];
if (messageNode != null) {
this.message = SDK.innerHTML(messageNode);
}
}
this.toXML = function() {
var xml = "");
if (this.subject != null) {
xml = xml + ("");
xml = xml + (SDK.escapeHTML(this.subject));
xml = xml + ("");
}
if (this.message != null) {
xml = xml + ("");
xml = xml + (SDK.escapeHTML(this.message));
xml = xml + ("");
}
xml = xml + ("");
return xml;
}
}
UserMessageConfig.prototype = new Config();
UserMessageConfig.prototype.constructor = UserMessageConfig;
UserMessageConfig.constructor = UserMessageConfig;
/**
* This object models a response config.
* It is used to add bot's question and response and other data associate with response.
* It can convert itself to/from XML for web API usage.
* This can be used to create, edit, bot's responses.
* @class
* @property type
* @property questionId
* @property responseId
* @property question
* @property response
* @property previous
* @property next
* @property onRepeat
* @property command
* @property think
* @property condition
* @property label
* @property topic
* @property keywords
* @property required
* @property emotions
* @property actions
* @property poses
* @property noRepeat
* @property requirePrevious
* @property requireTopic
* @property flagged
* @property correctness
*/
function ResponseConfig() {
this.type;
this.parentQuestionId;
this.parentResponseId;
this.questionId;
this.responseId;
this.metaId;
this.question;
this.response;
this.previous;
this.next;
this.onRepeat;
this.command;
this.think;
this.condition;
this.label;
this.topic;
this.keywords;
this.required;
this.emotions;
this.actions;
this.poses;
this.noRepeat;
this.requirePrevious;
this.requireTopic;
this.flagged;
this.correctness;
this.sentiment;
this.exclusiveTopic;
this.displayHTML;
this.autoReduce;
this.parseXML = function(element) {
this.type = element.getAttribute("type");
this.parentQuestionId = element.getAttribute("parentQuestionId");
this.parentResponseId = element.getAttribute("parentResponseId");
this.questionId = element.getAttribute("questionId");
this.responseId = element.getAttribute("responseId");
this.metaId = element.getAttribute("metaId");
this.question = element.getAttribute("question");
this.response = element.getAttribute("response");
this.previous = element.getAttribute("previous");
this.next = element.getAttribute("next");
this.onRepeat = element.getAttribute("onRepeat");
this.command = element.getAttribute("command");
this.think = element.getAttribute("think");
this.condition = element.getAttribute("condition");
this.label = element.getAttribute("label");
this.topic = element.getAttribute("topic");
this.keywords = element.getAttribute("keywords");
this.required = element.getAttribute("required");
this.emotions = element.getAttribute("emotions");
this.actions = element.getAttribute("actions");
this.poses = element.getAttribute("poses");
this.noRepeat = element.getAttribute("noRepeat");
this.requirePrevious = element.getAttribute("requirePrevious");
this.requireTopic = element.getAttribute("requireTopic");
this.flagged = element.getAttribute("flagged") == "true";
this.correctness = element.getAttribute("correctness");
this.sentiment = element.getAttribute("sentiment");
this.exclusiveTopic = element.getAttribute("exclusiveTopic");
this.displayHTML = element.getAttribute("displayHTML");
this.autoReduce = element.getAttribute("autoReduce") == "true";
var node = element.getElementsByTagName("question")[0];
if (node != null) {
this.question = SDK.innerHTML(node);
}
var node = element.getElementsByTagName("response")[0];
if (node != null) {
this.response = SDK.innerHTML(node);
}
var node = element.getElementsByTagName("previous")[0];
if (node != null) {
this.previous = SDK.innerHTML(node);
}
var node = element.getElementsByTagName("next")[0];
if (node != null) {
this.next = SDK.innerHTML(node);
}
var node = element.getElementsByTagName("onRepeat")[0];
if (node != null) {
this.onRepeat = SDK.innerHTML(node);
}
var node = element.getElementsByTagName("command")[0];
if (node != null) {
this.command = SDK.innerHTML(node);
}
var node = element.getElementsByTagName("think")[0];
if (node != null) {
this.think = SDK.innerHTML(node);
}
var node = element.getElementsByTagName("condition")[0];
if (node != null) {
this.condition = SDK.innerHTML(node);
}
}
this.toXML = function() {
var xml = "");
if (this.question != null) {
xml = xml + ("" + SDK.escapeHTML(this.question) + "");
}
if (this.response != null) {
xml = xml + ("" + SDK.escapeHTML(this.response) + "");
}
if (this.previous) {
xml = xml + ("" + SDK.escapeHTML(this.previous) + "");
}
if (this.next != null) {
xml = xml + ("" + SDK.escapeHTML(this.next) + "");
}
if (this.onRepeat != null) {
xml = xml + ("" + SDK.escapeHTML(this.onRepeat) + "");
}
if (this.command) {
xml = xml + ("" + SDK.escapeHTML(this.command) + "");
}
if (this.think) {
xml = xml + ("" + SDK.escapeHTML(this.think) + "");
}
if (this.condition) {
xml = xml + ("" + SDK.escapeHTML(this.condition) + "");
}
xml = xml + ("");
return xml;
}
}
ResponseConfig.prototype = new Config();
ResponseConfig.prototype.constructor = ResponseConfig;
ResponseConfig.constructor = ResponseConfig;
/**
* This object models a bot response search.
* It is used to query a bot's responses.
* It can convert itself to/from XML for web API usage.
* @class
* @property responseType
* @property inputType
* @property filter
* @property duration
* @property restrict
* @property page
*/
function ResponseSearchConfig() {
this.type;
this.parentQuestionId;
this.parentResponseId;
this.questionId;
this.responseId;
this.metaId;
this.question;
this.parseXML = function(element) {
this.responseType = element.getAttribute("responseType");
this.inputType = element.getAttribute("inputType");
this.filter = element.getAttribute("filter");
this.questionId = element.getAttribute("duration");
this.restrict = element.getAttribute("restrict");
this.page = element.getAttribute("page");
}
this.toXML = function() {
var xml = "");
xml = xml + ("");
return xml;
}
}
ResponseSearchConfig.prototype = new Config();
ResponseSearchConfig.prototype.constructor = ResponseSearchConfig;
ResponseSearchConfig.constructor = ResponseSearchConfig;
/**
* This object models a chat message sent to a chat bot instance.
* It can be used from a chat UI, or with the Libre Web API.
* It can convert itself to XML for web API usage.
* @class
* @property conversation
* @property speak
* @property correction
* @property offensive
* @property disconnect
* @property emote
* @property action
* @property message
* @property debug
* @property debugLevel
* @property learn
*/
function ChatConfig() {
/** The conversation id for the message. This will be returned from the first response, and must be used for all subsequent messages to maintain the conversational state. Without the conversation id, the bot has no context for the reply. */
this.conversation;
/** Sets if the voice audio should be generated for the bot's response. */
this.speak;
/** Sets the message to be a correction to the bot's last response. */
this.correction;
/** Flags the bot's last response as offensive. */
this.offensive;
/** Ends the conversation. Conversation should be terminated to converse server resources. The message can be blank. */
this.disconnect;
/**
* Attaches an emotion to the user's message, one of:
* NONE,
* LOVE, LIKE, DISLIKE, HATE,
* RAGE, ANGER, CALM, SERENE,
* ECSTATIC, HAPPY, SAD, CRYING,
* PANIC, AFRAID, CONFIDENT, COURAGEOUS,
* SURPRISE, BORED,
* LAUGHTER, SERIOUS
*/
this.emote;
/** Attaches an action to the user's messages, such as "laugh", "smile", "kiss". */
this.action;
/** The user's message text. */
this.message;
/** Include the message debug log in the response. */
this.debug;
/** Set the debug level, one of: SEVER, WARNING, INFO, CONFIG, FINE, FINER. */
this.debugLevel;
/** Enable or disable the bot's learning for this message. */
this.learn;
/** Escape and filter the response message HTML content for XSS security. */
this.secure = SDK.secure;
/** Strip any HTML tags from the response message. */
this.plainText;
/** Send extra info with the message, such as the user's contact info (name email phone). */
this.info;
/** Request a specific avatar (by ID). */
this.avatar;
/** Request the response avatar media in HD. */
this.avatarHD = SDK.hd;
/** Request the response avatar media in a video or image format. */
this.avatarFormat = SDK.format;
/** Translate between the user's language and the bot's language. */
this.language;
this.toXML = function() {
var xml = "");
if (this.message != null) {
xml = xml + ("");
xml = xml + (SDK.escapeHTML(this.message));
xml = xml + ("");
}
xml = xml + ("");
return xml;
}
}
ChatConfig.prototype = new Config();
ChatConfig.prototype.constructor = ChatConfig;
ChatConfig.constructor = ChatConfig;
/**
* This object models a command message sent to a bot instance.
* It can be used to send JSON events and commands to the bot to process.
* It can convert itself to XML for web API usage.
* @class
* @property conversation
* @property speak
* @property correction
* @property offensive
* @property disconnect
* @property emote
* @property action
* @property command
* @property debug
* @property debugLevel
* @property learn
*/
function CommandConfig() {
/** The conversation id for the message. This will be returned from the first response, and must be used for all subsequent messages to maintain the conversational state. Without the conversation id, the bot has no context for the reply. */
this.conversation;
/** Sets if the voice audio should be generated for the bot's response. */
this.speak;
/** Sets the message to be a correction to the bot's last response. */
this.correction;
/** Flags the bot's last response as offensive. */
this.offensive;
/** Ends the conversation. Conversation should be terminated to converse server resources. The message can be blank. */
this.disconnect;
/**
* Attaches an emotion to the user's message, one of:
* NONE,
* LOVE, LIKE, DISLIKE, HATE,
* RAGE, ANGER, CALM, SERENE,
* ECSTATIC, HAPPY, SAD, CRYING,
* PANIC, AFRAID, CONFIDENT, COURAGEOUS,
* SURPRISE, BORED,
* LAUGHTER, SERIOUS
*/
this.emote;
/** Attaches an action to the user's messages, such as "laugh", "smile", "kiss". */
this.action;
/** The json command. */
this.command;
/** Include the message debug log in the response. */
this.debug;
/** Set the debug level, one of: SEVER, WARNING, INFO, CONFIG, FINE, FINER. */
this.debugLevel;
/** Enable or disable the bot's learning for this message. */
this.learn;
/** Escape and filter the response message HTML content for XSS security. */
this.secure = SDK.secure;
/** Strip any HTML tags from the response message. */
this.plainText;
/** Send extra info with the message, such as the user's contact info (name email phone). */
this.info;
/** Request a specific avatar (by ID). */
this.avatar;
/** Request the response avatar media in HD. */
this.avatarHD = SDK.hd;
/** Request the response avatar media in a video or image format. */
this.avatarFormat = SDK.format;
/** Translate between the user's language and the bot's language. */
this.language;
this.toXML = function() {
var xml = "");
if (this.command != null) {
xml = xml + ("");
xml = xml + (SDK.escapeHTML(this.command));
xml = xml + ("");
}
xml = xml + ("");
return xml;
}
}
CommandConfig.prototype = new Config();
CommandConfig.prototype.constructor = CommandConfig;
CommandConfig.constructor = CommandConfig;
/**
* This object models a chat message received from a chat bot instance.
* It can be used from a chat UI, or with the Libre Web API.
* It can convert itself from XML for web API usage.
* @class
* @property conversation
* @property avatar
* @property avatarType
* @property avatarTalk
* @property avatarTalkType
* @property avatarAction
* @property avatarActionType
* @property avatarActionAudio
* @property avatarActionAudioType
* @property avatarAudio
* @property avatarAudioType
* @property avatarBackground
* @property speech
* @property message
* @property question
* @property emote
* @property action
* @property pose
* @property command
* @property log
*/
function ChatResponse() {
/** The conversation id for the message. This will be returned from the first response, and must be used for all subsequent messages to maintain the conversational state. Without the conversation id, the bot has no context for the reply. */
this.conversation;
/** Server relative URL for the avatar image or video. */
this.avatar;
/** Second avatar animation. */
this.avatar2;
/** Third avatar animation. */
this.avatar3;
/** Forth avatar animation. */
this.avatar4;
/** Fifth avatar animation. */
this.avatar5;
/** Avatar MIME file type, (mpeg, webm, ogg, jpeg, png) */
this.avatarType;
/** Server relative URL for the avatar talking image or video. */
this.avatarTalk;
/** Avatar talk MIME file type, (mpeg, webm, ogg, jpeg, png) */
this.avatarTalkType;
/** Server relative URL for the avatar action image or video. */
this.avatarAction;
/** Avatar action MIME file type, (mpeg, webm, ogg, jpeg, png) */
this.avatarActionType;
/** Server relative URL for the avatar action audio image or video. */
this.avatarActionAudio;
/** Avatar action audio MIME file type, (mpeg, wav) */
this.avatarActionAudioType;
/** Server relative URL for the avatar audio image or video. */
this.avatarAudio;
/** Avatar audio MIME file type, (mpeg, wav) */
this.avatarAudioType;
/** Server relative URL for the avatar background image. */
this.avatarBackground;
/** Server relative URL for the avatar speech audio file. */
this.speech;
/** The bot's message text. */
this.message;
/** Optional text to the original question. */
this.question;
/**
* Emotion attached to the bot's message, one of:
* NONE,
* LOVE, LIKE, DISLIKE, HATE,
* RAGE, ANGER, CALM, SERENE,
* ECSTATIC, HAPPY, SAD, CRYING,
* PANIC, AFRAID, CONFIDENT, COURAGEOUS,
* SURPRISE, BORED,
* LAUGHTER, SERIOUS
*/
this.emote;
/** Action for the bot's messages, such as "laugh", "smile", "kiss", or mobile directive (for virtual assistants). */
this.action;
/** Pose for the bot's messages, such as "dancing", "sitting", "sleeping". */
this.pose;
/** JSON Command for the bot's message. This can be by the client for mobile virtual assistant functionality, games integration, or other uses. */
this.command;
/** The debug log of processing the message. */
this.log;
this.parseXML = function(element) {
this.conversation = element.getAttribute("conversation");
this.avatar = element.getAttribute("avatar");
this.avatar2 = element.getAttribute("avatar2");
this.avatar3 = element.getAttribute("avatar3");
this.avatar4 = element.getAttribute("avatar4");
this.avatar5 = element.getAttribute("avatar5");
this.avatarType = element.getAttribute("avatarType");
this.avatarTalk = element.getAttribute("avatarTalk");
this.avatarTalkType = element.getAttribute("avatarTalkType");
this.avatarAction = element.getAttribute("avatarAction");
this.avatarActionType = element.getAttribute("avatarActionType");
this.avatarActionAudio = element.getAttribute("avatarActionAudio");
this.avatarActionAudioType = element.getAttribute("avatarActionAudioType");
this.avatarAudio = element.getAttribute("avatarAudio");
this.avatarAudioType = element.getAttribute("avatarAudioType");
this.avatarBackground = element.getAttribute("avatarBackground");
this.emote = element.getAttribute("emote");
this.action = element.getAttribute("action");
this.pose = element.getAttribute("pose");
this.command = element.getAttribute("command");
this.speech = element.getAttribute("speech");
var node = element.getElementsByTagName("message")[0];
if (node != null) {
this.message = SDK.innerHTML(node);
}
node = element.getElementsByTagName("log")[0];
if (node != null) {
this.log = SDK.innerHTML(node);
}
}
}
ChatResponse.prototype = new Config();
ChatResponse.prototype.constructor = ChatResponse;
ChatResponse.constructor = ChatResponse;
/**
* This object models an analytic message received from an analytic instance.
* @class
* @property label
* @property confidence
*/
function AnalyticResponse() {
/** result that is comming from the trained labels, the name of the image */
this.labels = [];
/** result that is coming from the trained graph, the percentage of the image*/
this.confidences = [];
this.parseXML = function(element) {
this.parseWebMediumXML(element);
var nodes = element.getElementsByTagName("result");
for (var i = 0; i < nodes.length; i++) {
if(nodes[i] !=null){
this.labels.push(nodes[i].getAttribute("label"));
this.confidences.push(nodes[i].getAttribute("confidence"));
}
}
}
}
AnalyticResponse.prototype = new WebMediumConfig();
AnalyticResponse.prototype.constructor = AnalyticResponse;
AnalyticResponse.constructor = AnalyticResponse;
/**
* This object models an analytic test media received from an analytic instance.
* @class
* @property actualLabel
* @property actualConfidecne
* @property expectedLabel
* @property ExpectedConfidence
*/
function AnalyticTestMediaResponse() {
this.listOfResponses = [];
this.parseXML = function(element) {
this.parseWebMediumXML(element);
var nodes = element.getElementsByTagName("analytic-test-result");
if (nodes.length == 0) {
nodes = element.getElementsByTagName("analytic-object-detection-response");
}
this.startTime = element.getAttribute("starttime");
this.endTime = element.getAttribute("endtime");
this.elapsedTime = element.getAttribute("elapsedtime");
var i;
for (i = 0; i < nodes.length; i++) {
if(nodes[i] !=null){
var singleResult = {};
singleResult['name'] = nodes[i].getAttribute("name");
singleResult['image'] = nodes[i].getAttribute("image");
singleResult['testTime'] = nodes[i].getAttribute("testtime");
singleResult['actualLabel'] = nodes[i].getAttribute("actuallabel");
singleResult['actualConfidence'] = nodes[i].getAttribute("actualconfidence");
singleResult['expectedLabel'] = nodes[i].getAttribute("expectedlabel");
singleResult['expectedConfidence'] = nodes[i].getAttribute("expectedconfidence");
this.listOfResponses.push(singleResult);
}
}
}
}
AnalyticTestMediaResponse.prototype = new WebMediumConfig();
AnalyticTestMediaResponse.prototype.constructor = AnalyticTestMediaResponse;
AnalyticTestMediaResponse.constructor = AnalyticTestMediaResponse;
/**
* This object models an analytic message received from an analytic instance.
* @class
* @property label
* @property confidence
*/
function AnalyticAudioResponse() {
this.label;
this.confidence;
this.parseXML = function(element) {
this.parseWebMediumXML(element);
this.label = element.getAttribute("label");
this.confidence = element.getAttribute("confidence");
}
this.toXML = function() {
var xml = "");
return xml;
}
}
AnalyticAudioResponse.prototype = new WebMediumConfig();
AnalyticAudioResponse.prototype.constructor = AnalyticAudioResponse;
AnalyticAudioResponse.constructor = AnalyticAudioResponse;
/**
* This object models an analytic message received from an analytic instance.
* @class
* @property label
* @property confidence
*/
function AnalyticObjectDetectionResponse() {
this.image;
this.numberOfClasses;
this.result = [];
this.bottom;
this.left;
this.top;
this.right;
this.parseXML = function(element) {
//this.name = element.getAttribute("name");
console.log(element);
var node = element.getElementsByTagName("image")[0];
if (node != null) {
this.image = SDK.innerHTML(node);
}
node = element.getElementsByTagName("numberOfClasses")[0];
if (node != null) {
this.numberOfClasses = SDK.innerHTML(node);
}
var nodes = element.getElementsByTagName("result");
for (var i = 0; i < nodes.length; i++) {
if(nodes[i] != null){
this.result.push(nodes[i].getAttribute("label") + ": " + nodes[i].getAttribute("confidence") + "%");
let box = nodes[i].getElementsByTagName("box")[0];
this.bottom = box.getAttribute("bottom");
this.left = box.getAttribute("left");
this.top = box.getAttribute("top");
this.right = box.getAttribute("right");
//console.log(box.getAttribute("bottom") + ", " + box.getAttribute("left")+ ", " + box.getAttribute("top")+ ", " + box.getAttribute("right"));
}
}
}
this.toXML = function() {
var xml = "";
if (this.image != null) {
xml = xml + ("" + this.image + "");
}
if (this.numberOfClasses != null) {
xml = xml + ("" + this.numberOfClasses + "");
}
result.forEach(function(x){
if(x != null){
xml = xml + ("" + x + "")
}
});
xml = this.writeWebMediumXML(xml);
xml = xml + ("");
return xml;
}
}
AnalyticObjectDetectionResponse.prototype = new Config();
AnalyticObjectDetectionResponse.prototype.constructor = AnalyticObjectDetectionResponse;
AnalyticObjectDetectionResponse.constructor = AnalyticObjectDetectionResponse;
/**
* This object models an analytic message received from an NLP analytic instance.
* @class
* @property label
* @property confidence
*/
function AnalyticNlpResponse() {
this.label;
this.confidence;
this.parseXML = function(element) {
this.parseWebMediumXML(element);
this.label = element.getAttribute("label");
this.confidence = element.getAttribute("confidence");
}
this.toXML = function() {
var xml = "");
return xml;
}
}
AnalyticNlpResponse.prototype = new WebMediumConfig();
AnalyticNlpResponse.prototype.constructor = AnalyticNlpResponse;
AnalyticNlpResponse.constructor = AnalyticNlpResponse;
/**
* This object is returned from the SDK chatSettings() API to retrieve a conversation's chat settings.
* It can convert itself from XML for web API usage.
* @class
* @property conversation
* @property allowEmotes
* @property allowCorrection
* @property allowLearning
* @property learning
*/
function ChatSettings() {
this.conversation;
this.allowEmotes;
this.allowCorrection;
this.allowLearning;
this.learning;
this.toXML = function() {
var xml = "");
return xml;
}
this.parseXML = function(element) {
this.allowEmotes = "true" == (element.getAttribute("allowEmotes"));
this.allowCorrection = "true" == (element.getAttribute("allowCorrection"));
this.allowLearning = "true" == (element.getAttribute("allowLearning"));
this.learning = "true" == (element.getAttribute("learning"));
}
}
ChatSettings.prototype = new Config();
ChatSettings.prototype.constructor = ChatSettings;
ChatSettings.constructor = ChatSettings;
/**
* DTO for XML avatar message config.
* @class
* @property avatar
* @property speak
* @property voice
* @property message
* @property emote
* @property action
* @property pose
*/
function AvatarMessage() {
this.avatar;
this.speak;
this.voice;
this.nativeVoiceName
this.voiceMod;
this.message;
this.emote;
this.action;
this.voiceProvider;
this.apiKey;
this.apiEndpoint;
this.pose;
this.hd = SDK.hd;
this.format = SDK.format;
this.toXML = function() {
var xml = "");
if (this.message != null) {
xml = xml + ("");
xml = xml + (SDK.escapeHTML(this.message));
xml = xml + ("");
}
xml = xml + ("");
return xml;
}
}
AvatarMessage.prototype = new Config();
AvatarMessage.prototype.constructor = AvatarMessage;
AvatarMessage.constructor = AvatarMessage;
/**
* DTO for XML user avatar message config.
* @class
* @property userAvatar
* @property speak
* @property voice
* @property message
* @property emote
* @property action
* @property pose
*/
function UserAvatarMessage() {
this.userAvatar;
this.speak;
this.voice;
this.voiceMod;
this.message;
this.emote;
this.action;
this.pose;
this.hd = SDK.hd;
this.format = SDK.format;
this.toXML = function() {
var xml = "");
if (this.message != null) {
xml = xml + ("");
xml = xml + (SDK.escapeHTML(this.message));
xml = xml + ("");
}
xml = xml + ("");
return xml;
}
}
UserAvatarMessage.prototype = new Config();
UserAvatarMessage.prototype.constructor = UserAvatarMessage;
UserAvatarMessage.constructor = UserAvatarMessage;
/**
* This object models the web API browse operation.
* It can be used to search a set of instances (bots, forums, or channels).
* @class
* @property type
* @property typeFilter
* @property category
* @property tag
* @property filter
* @property sort
*/
function BrowseConfig() {
/** Filters instances by access type, "Public", "Private", "Personal". */
this.typeFilter;
/** Filters instances by categories (csv) */
this.category;
/** Filters instances by tags (csv) */
this.tag;
/** Filters instances by name */
this.filter;
/** Sorts instances, "name", "date", "size", "stars", "thumbs up", "thumbs down", "last connect", "connects", "connects today", "connects this week ", "connects this month" */
this.sort;
/** Indicates a particular page of results */
this.page;
this.toXML = function() {
var xml = "");
return xml;
}
}
BrowseConfig.prototype = new Config();
BrowseConfig.prototype.constructor = BrowseConfig;
BrowseConfig.constructor = BrowseConfig;
/**
* Abstract content class.
* This object models a content object such as a bot, forum, or channel.
* It can be used from a chat UI, or with the Libre Web API.
* It can convert itself to/from XML for web API usage.
* This can be used to create, edit, or browse a content.
* @class
* @property id
* @property name
* @property isAdmin
* @property isAdult
* @property isPrivate
* @property isHidden
* @property accessMode
* @property isFlagged
* @property flaggedReason
* @property isExternal
* @property description
* @property details
* @property disclaimer
* @property tags
* @property categories
* @property creator
* @property creationDate
* @property lastConnectedUser
* @property website
* @property license
* @property avatar
* @property connects
* @property dailyConnects
* @property weeklyConnects
* @property monthlyConnects
*/
function WebMediumConfig() {
/** Instance ID. */
this.id;
/** Instance name. */
this.name;
/** Instance alias. */
this.alias;
/** Read-only, returns if connected user is the content's admin. */
this.isAdmin;
this.isAdult;
/** Sets if the content is private to the creator, and its members. */
this.isPrivate;
/** Sets if the conent will be visible and searchable in the content directory. */
this.isHidden;
/** Sets the access mode for the content, ("Everyone", "Users", "Members", "Administrators"). */
this.accessMode;
/** Returns if the content has been flagged, or used to flag content as offensive (reason required). */
this.isFlagged;
/** Returns why the content has been flagged, or used to flag content as offensive. */
this.flaggedReason;
/** Can be used to create a link to external content in the content directory. */
this.isExternal;
/** Optional description of the content. */
this.description;
/** Optional restrictions or details of the content. */
this.details;
/** Optional warning or disclaimer of the content. */
this.disclaimer;
/** Tags to classify the content (csv). */
this.tags;
/** Categories to categorize the content under (csv). */
this.categories;
/** Read-only, returns content's creator's user ID. */
this.creator;
/** Read-only, returns content's creation date. */
this.creationDate;
/** Read-only, returns last user to access content */
this.lastConnectedUser;
/** Optional license to license the content under. */
this.license;
/** Optional website related to the content. */
this.website = "";
/** Read-only, server local URL to content's avatar image. */
this.avatar;
/** Read-only, returns content's toal connects. */
this.connects;
/** Read-only, returns content's daily connects. */
this.dailyConnects;
/** Read-only, returns content's weekly connects. */
this.weeklyConnects;
/** Read-only, returns content's monthly connects. */
this.monthlyConnects;
this.writeWebMediumXML = function(xml) {
xml = this.writeCredentials(xml);
if (this.id != null) {
xml = xml + (" id=\"" + this.id + "\"");
}
if (this.name != null) {
xml = xml + (" name=\"" + this.name + "\"");
}
if (this.alias != null) {
xml = xml + (" alias=\"" + this.alias + "\"");
}
if (this.isPrivate) {
xml = xml + (" isPrivate=\"true\"");
}
if (this.isHidden) {
xml = xml + (" isHidden=\"true\"");
}
if (this.accessMode != null && this.accessMode != "") {
xml = xml + (" accessMode=\"" + this.accessMode + "\"");
}
if (this.isAdult) {
xml = xml + (" isAdult=\"true\"");
}
if (this.isFlagged) {
xml = xml + (" isFlagged=\"true\"");
}
xml = xml + (">");
if (this.description != null) {
xml = xml + ("");
xml = xml + (SDK.escapeHTML(this.description));
xml = xml + ("");
}
if (this.details != null) {
xml = xml + ("");
xml = xml + (SDK.escapeHTML(this.details));
xml = xml + ("");
}
if (this.disclaimer != null) {
xml = xml + ("");
xml = xml + (SDK.escapeHTML(this.disclaimer));
xml = xml + ("");
}
if (this.categories != null) {
xml = xml + ("");
xml = xml + (SDK.escapeHTML(this.categories));
xml = xml + ("");
}
if (this.tags != null) {
xml = xml + ("");
xml = xml + (SDK.escapeHTML(this.tags));
xml = xml + ("");
}
if (this.license != null) {
xml = xml + ("");
xml = xml + (SDK.escapeHTML(this.license));
xml = xml + ("");
}
if (this.flaggedReason != null) {
xml = xml + ("");
xml = xml + (SDK.escapeHTML(this.flaggedReason));
xml = xml + ("");
}
return xml;
}
this.parseWebMediumXML = function(element) {
this.id = element.getAttribute("id");
this.name = element.getAttribute("name");
this.alias = element.getAttribute("alias");
this.creationDate = element.getAttribute("creationDate");
this.isPrivate = element.getAttribute("isPrivate") == "true";
this.isHidden = element.getAttribute("isHidden") == "true";
this.accessMode = element.getAttribute("accessMode");
this.isAdmin = element.getAttribute("isAdmin") == "true";
this.isAdult = element.getAttribute("isAdult") == "true";
this.isFlagged = element.getAttribute("isFlagged") == "true";
this.creator = element.getAttribute("creator");
this.creationDate = element.getAttribute("creationDate");
this.connects = element.getAttribute("connects");
this.dailyConnects = element.getAttribute("dailyConnects");
this.weeklyConnects = element.getAttribute("weeklyConnects");
this.monthlyConnects = element.getAttribute("monthlyConnects");
var node = element.getElementsByTagName("description")[0];
if (node != null) {
this.description = SDK.innerHTML(node);
}
node = element.getElementsByTagName("details")[0];
if (node != null) {
this.details = SDK.innerHTML(node);
}
node = element.getElementsByTagName("disclaimer")[0];
if (node != null) {
this.disclaimer = SDK.innerHTML(node);
}
node = element.getElementsByTagName("categories")[0];
if (node != null) {
this.categories = SDK.innerHTML(node);
}
node = element.getElementsByTagName("tags")[0];
if (node != null) {
this.tags = SDK.innerHTML(node);
}
node = element.getElementsByTagName("flaggedReason")[0];
if (node != null) {
this.flaggedReason = SDK.innerHTML(node);
}
node = element.getElementsByTagName("lastConnectedUser")[0];
if (node != null) {
this.lastConnectedUser = SDK.innerHTML(node);
}
node = element.getElementsByTagName("license")[0];
if (node != null) {
this.license = SDK.innerHTML(node);
}
node = element.getElementsByTagName("avatar")[0];
if (node != null) {
this.avatar = SDK.innerHTML(node);
}
}
}
WebMediumConfig.prototype = new Config();
WebMediumConfig.prototype.constructor = WebMediumConfig;
WebMediumConfig.constructor = WebMediumConfig;
/**
* This object models a live chat channel or chatroom instance.
* It can be used from a chat UI, or with the Libre Web API.
* It can convert itself to/from XML for web API usage.
* This can be used to create, edit, or browse a channel instance.
* @class
* @property type
* @property messages
* @property usersOnline
* @property adminsOnline
*/
function ChannelConfig() {
/** Sets type, "ChatRoom", "OneOnOne". */
this.type;
/** Read-only: total number of messages. */
this.messages;
/** Read-only: current users online. */
this.usersOnline;
/** Read-only: current admins or operators online. */
this.adminsOnline;
this.type = "channel";
this.credentials = function() {
var config = new ChannelConfig();
config.id = this.id;
return config;
}
this.toXML = function() {
var xml = "");
return xml;
}
this.parseXML = function(element) {
this.parseWebMediumXML(element);
this.type = element.getAttribute("type");
this.messages = element.getAttribute("messages");
this.usersOnline = element.getAttribute("usersOnline");
this.adminsOnline = element.getAttribute("adminsOnline");
}
}
ChannelConfig.prototype = new WebMediumConfig();
ChannelConfig.prototype.constructor = ChannelConfig;
ChannelConfig.constructor = ChannelConfig;
/**
* DTO to parse response of a list of names.
* This is used for categories, tags, and templates.
* @class
* @property type
*/
function ContentConfig() {
this.type;
this.parseXML = function(element) {
this.type = element.getAttribute("type");
}
this.toXML = function() {
var xml = "");
return xml;
}
}
ContentConfig.prototype = new Config();
ContentConfig.prototype.constructor = ContentConfig;
ContentConfig.constructor = ContentConfig;
/**
* This object models a domain.
* It can be used from a chat UI, or with the Libre Web API.
* A domain is an isolated content space to create bots and other content in (such as a commpany, project, or school).
* It can convert itself to/from XML for web API usage.
* This can be used to create, edit, or browse a domain instance.
* @class
* @property creationMode
*/
function DomainConfig() {
this.creationMode;
this.type = "domain";
this.credentials = function() {
var config = new DomainConfig();
config.id = this.id;
return config;
}
this.toXML = function() {
var xml = "");
return xml;
}
this.parseXML = function(element) {
this.parseWebMediumXML(element);
this.creationMode = element.getAttribute("creationMode");
}
}
DomainConfig.prototype = new WebMediumConfig();
DomainConfig.prototype.constructor = DomainConfig;
DomainConfig.constructor = DomainConfig;
/**
* This object models an avatar.
* An avatar represents a bot's visual image, but can also be used independently with TTS.
* It can convert itself to/from XML for web API usage.
* This can be used to create, edit, or browse an avatar instance.
* @class
*/
function AvatarConfig() {
this.type = "avatar";
this.credentials = function() {
var config = new AvatarConfig();
config.id = this.id;
return config;
}
this.toXML = function() {
var xml = "");
return xml;
}
this.parseXML = function(element) {
this.parseWebMediumXML(element);
}
}
AvatarConfig.prototype = new WebMediumConfig();
AvatarConfig.prototype.constructor = AvatarConfig;
AvatarConfig.constructor = AvatarConfig;
/**
* This object models a script from the script library.
* It can convert itself to/from XML for web API usage.
* This can be used to create, edit, or browse an avatar instance.
* @class
*/
function ScriptConfig() {
this.type = "script";
this.credentials = function() {
var config = new AvatarConfig();
config.id = this.id;
return config;
}
this.toXML = function() {
var xml = "