node-red-contrib-chatbot
Version:
REDBot a Chat bot for a full featured chat bot for Telegram, Facebook Messenger and Slack. Almost no coding skills required
1,125 lines (1,044 loc) • 61.4 kB
HTML
<script type="text/javascript">
$.fn.RB_setComboWithPlatformLabels = function(value) {
var combo = $(this);
$(this).val(value);
var selected = $('option[value=' + value + ']', this);
combo
.attr('class')
.split(' ')
.forEach(function(className) {
if (className.indexOf('platform-') !== -1) {
combo.removeClass(className);
}
});
if (selected != null) {
combo.addClass(selected.attr('class'));
}
};
$.fn.RB_comboWithPlatformLabels = function() {
$(this)
.change(function() {
var combo = $(this);
var selected = $('option[value=' + combo.val() + ']', this);
combo
.attr('class')
.split(' ')
.forEach(function(className) {
if (className.indexOf('platform-') !== -1) {
combo.removeClass(className);
}
});
if (selected != null) {
combo.addClass(selected.attr('class'));
}
});
};
$.fn.RB_OptionsEditor = function(command, options) {
var container = $(this);
var defaultOptions = {
label: 'Options',
labelAdd: 'add'
};
if (arguments.length === 1 && typeof arguments[0] === 'object') {
options = $.extend({}, defaultOptions, arguments[0]);
command = 'init';
} else if (arguments.length === 0) {
command = 'init';
options = $.extend({}, defaultOptions);
} else if (arguments.length === 1 && arguments[0] === 'value') {
command = 'get_value';
} else if (arguments.length === 2 && arguments[0] === 'value') {
command = 'set_value';
}
var addRow = function(value, label) {
var count = $('.option', container);
$('<div class="option"/>').css('marginTop','5px')
.append('<div style="display:inline-block;width:6%;" class="order">' + (count.length + 1) + '.</div>')
.append($('<input style="width:35%" class="node-input-rule-type" type="text" name="value" placeholder="Value" value="' + value + '"/>'))
.append($('<input style="width:48%;margin-left: 5%" class="node-input-rule-type" type="text" name="label" placeholder="Label" value="' + label + '"/>'))
.append('<a href="#" class="btn-remove" style="width:5%;display:inline-block;"><i class="fa fa-times"></i></a>')
.appendTo($('.options', container));
};
switch(command) {
case 'init':
container
.addClass('rb-options-editor')
.on('click', '.btn-remove', function() {
$(this).parents('.option').remove();
$('.option', container).each(function(idx, item) {
$('.order', item).html(idx + 1);
});
});
$('<div class="control-description"/>')
.html(options.label)
.appendTo(container);
$('<div class="options"/>')
.appendTo(container);
$('<div class="button"/>')
.append('<a class="btn-add" href="#">' + options.labelAdd+ '</a>')
.appendTo(container);
$('a.btn-add', container)
.click(function(e) {
e.preventDefault();
addRow('', '');
});
break;
case 'get_value':
var values = [];
$('.option', container).each(function(idx, item) {
var value = $('input[name=value]', item).val();
var label = $('input[name=label]', item).val();
if (value === '' && label !== '') {
value = label;
} else if (value !== '' && label === '') {
label = value;
}
if (value !== '' && label !== '') {
values.push({
value: value,
label: label
});
}
});
return values;
case 'set_value':
$('.options').empty();
$(arguments[1]).each(function(idx, option) {
addRow(option.value, option.label);
});
break;
}
return container;
};
$.fn.RB_setElementData = function(obj, options) {
options = options || {};
options.badges = options.badges !== false;
var container = $(this);
var select = $('select[name=type]', container).val(obj.type);
var panel = $('.panel-' + obj.type, container).show();
var element = $.RedBot.elementTypes.findElement(obj.type);
if (element != null && options.badges) {
select.attr('class', element.className);
}
$('input[name="label"]', panel).val(obj.label);
$('input[name="name"]', panel).val(obj.name);
$('input[name="value"]', panel).val(obj.value);
$('input[name="placeholder"]', panel).val(obj.placeholder);
$('input[name="hint"]', panel).val(obj.hint);
$('select[name="subtype"]', panel).val(obj.subtype);
$('input[name="max_length"]', panel).val(obj.maxLength);
$('input[name="min_length"]', panel).val(obj.minLength);
$('input[name="optional"]', panel).attr('checked', obj.optional === true);
$('.container-options', panel).RB_OptionsEditor('value', obj.options);
return container;
};
$.fn.RB_setButtonData = function(obj, options) {
options = options || {};
options.badges = options.badges !== false;
var container = $(this);
var availablePlatforms = $.isArray(container.data('platforms')) ?
container.data('platforms') : ['facebook', 'telegram'];
var select = $('select[name=type]', container).val(obj.type);
var panel = $('.panel-' + obj.type, container).show();
var button = $.RedBot.buttonTypes.findButton(obj.type);
// update badges of select with intersection of available platforms and button compatibility
if (button != null && options.badges) {
$.RedBot.supportedBy($('.type-badges', container), $.RedBot.intersect(availablePlatforms, button.platforms));
//select.attr('class', $.RedBot.platformClass('select', $.RedBot.intersect(availablePlatforms, button.platforms)));
} else {
//select.attr('class', '');
$('.type-badges', container).empty();
}
$('input[name=label]', panel).val(obj.label);
$('input[name=url]', panel).val(obj.url);
$('input[name=value]', panel).val(obj.value);
$('input[name=number]', panel).val(obj.number);
$('input[name=answer]', panel).val(obj.answer);
$('input[name=alert]', panel).attr('checked', obj.alert === true);
$('select[name=webview_height_ratio]', panel).val(obj.webViewHeightRatio);
$('select[name=style]', panel).val(obj.style);
$('input[name=messenger_extensions]').attr('checked', obj.extensions === true);
return container;
};
$.fn.RB_getElementData = function() {
var container = $(this);
var type = $('select[name="type"]', container);
var panel = $('.panel-' + type.val(), container);
var label = $('input[name="label"]', panel);
var name = $('input[name="name"]', panel);
var value = $('input[name="value"]', panel);
var placeholder = $('input[name="placeholder"]', panel);
var hint = $('input[name="hint"]', panel);
var subtype = $('select[name="subtype"]', panel);
var maxLength = $('input[name="max_length"]', panel);
var minLength = $('input[name="min_length"]', panel);
var optional = $('input[name="optional"]', panel);
var options = $('.container-options', panel);
var result = null;
switch(type.val()) {
case 'text':
case 'textarea':
result = {
type: type.val(),
label: label.val(),
name: name.val(),
value: value.val(),
placeholder: placeholder.val(),
hint: hint.val(),
optional: optional.is(':checked')
};
if (subtype.val() !== '') {
result.subtype = subtype.val();
}
if (!isNaN(parseInt(maxLength.val(), 10))) {
result.maxLength = parseInt(maxLength.val(), 10);
}
if (!isNaN(parseInt(minLength.val(), 10))) {
result.minLength = parseInt(minLength.val(), 10);
}
break;
case 'select':
result = {
type: 'select',
label: label.val(),
name: name.val(),
options: options.RB_OptionsEditor('value')
};
break;
}
return result;
};
$.fn.RB_getButtonData = function() {
var container = $(this);
var type = $('select[name="type"]', container);
var panel = $('.panel-' + type.val(), container);
var label = $('input[name="label"]', panel);
var url = $('input[name="url"]', panel);
var value = $('input[name="value"]', panel);
var number = $('input[name="number"]', panel);
var answer = $('input[name="answer"]', panel);
var alert = $('input[name="alert"]', panel);
var style = $('select[name="style"]', panel);
var messengerExtensions = $('input[name="messenger_extensions"]', panel);
var webViewHeight = $('select[name="webview_height_ratio"]', panel);
var result = null;
switch(type.val()) {
case 'keyboardButton':
result = {
type: 'keyboardButton',
label: label.val()
};
break;
case 'url':
result = {
type: 'url',
label: label.val(),
url: url.val(),
webViewHeightRatio: webViewHeight.val(),
extensions: messengerExtensions.is(':checked'),
answer: answer.val(),
alert: alert.is(':checked')
};
break;
case 'call':
result = {
type: 'call',
label: label.val(),
number: number.val()
};
break;
case 'postback':
result = {
type: 'postback',
label: label.val(),
value: value.val(),
answer: answer.val(),
alert: alert.is(':checked'),
style: style.val()
};
break;
case 'dialog':
result = {
type: 'dialog',
label: label.val(),
value: value.val(),
answer: answer.val(),
alert: alert.is(':checked'),
style: style.val()
};
break;
case 'quick-reply':
result = {
type: 'quick-reply',
label: label.val(),
value: value.val(),
url: url.val()
};
break;
case 'newline':
result = {
type: 'newline'
};
break;
case 'location':
result = {
type: 'location'
};
break;
case 'share':
result = {
type: 'share'
};
break;
case 'logout':
result = {
type: 'logout'
};
break;
case 'login':
result = {
type: 'login',
url: url.val()
};
break;
case 'phone':
result = {
type: 'phone'
};
break;
case 'email':
result = {
type: 'email'
};
break;
}
return result;
};
$.fn.RB_hasPlatform = function(platform, platforms) {
platform = platform instanceof Array ? platform : [platform];
var hasMatch = false;
for(var idx = 0; idx < platform.length; idx++) {
if (platforms.indexOf(platform[idx]) !== -1) {
hasMatch = true;
}
}
return hasMatch ? $(this) : $();
};
$.fn.RB_mountButtonDialog = function(options) {
options = options || {};
options.types = options.types != null ?
options.types : ['url', 'postback', 'call', 'share', 'login', 'newline', 'logout', 'location', 'quick-reply', 'dialog', 'key', 'email', 'phone'];
options.platforms = options.platforms != null ? options.platforms : ['facebook', 'telegram'];
options.badges = options.badges !== false;
var container = $(this);
// store available platforms in the container
container.data('platforms', options.platforms);
var main = $('<div/>').appendTo(container);
var cx = options.badges ? $.RedBot.platformClass : function() { return ''; };
var selectButtonType = $('<select name="type"/>', { style:"width:200px; margin-left: 5px; text-align: center;" })
.attr('placeholder', 'Select button type')
.change(function() {
var type = $(this).val();
$('.panel', container).hide();
$('.panel-' + type, container).show();
// find the right button
var button = $.RedBot.buttonTypes.findButton(type);
// store class only if badges should be shown
if (button != null && options.badges) {
//$(this).attr('class', cx('select', $.RedBot.intersect(options.platforms, button.platforms)));
$.RedBot.supportedBy($('.type-badges', main), $.RedBot.intersect(options.platforms, button.platforms));
} else {
//$(this).attr('class', '');
$('.type-badges', main).empty();
}
})
.appendTo(main);
$('<div class="type-badges" style="margin-left:5px;display:inline-block;"></div>').appendTo(main);
selectButtonType.append($('<option value="">Select button type</option>'));
$.RedBot.buttonTypes.forEach(function(button) {
if (options.types.indexOf(button.type) !== -1 && $.RedBot.platforms(options.platforms, button.platforms)) {
selectButtonType.append($('<option value="' + button.type + '">' + button.label + '</option>'));
}
});
var panelUrl = $('<div class="panel panel-url" style="display:none;"/>').appendTo(container);
$('<div/>').css('marginTop','5px')
.append($('<input style="width:100%" class="node-input-rule-type" type="text" name="label" placeholder="Button label"/>'))
.appendTo(panelUrl);
$('<div/>').css('marginTop','5px')
.append($('<input style="width:100%" class="node-input-rule-type" type="text" name="url" placeholder="Button URL"/>'))
.appendTo(panelUrl);
$('<div/>').css('marginTop','5px')
.RB_hasPlatform('telegram', options.platforms)
.append('<input class="node-input-rule-type" type="text" name="answer" style="width:60%" placeholder="Button feedback"/>')
.append('<div class="redbot-platforms telegram"/>')
.append('<input type="checkbox" name="alert" value="on" style="width:auto;margin:0px 10px 5px 10px;"/>')
.append('<span>With popup</span>')
.append('<div class="redbot-platforms telegram"/>')
.appendTo(panelUrl);
$('<div/>').css('marginTop','5px')
.RB_hasPlatform('facebook', options.platforms)
.append('<select name="webview_height_ratio" style="width:60%">'
+ '<option value="tall">Tall</option>'
+ '<option value="compact">Compact</option>'
+ '<option value="full">Full</option>'
+ '</select>')
.append('<div class="redbot-platforms facebook"/>')
.append('<input type="checkbox" name="messenger_extensions" value="on" style="width: auto;margin:0px 10px 5px 10px;"/>')
.append('<span>Extensions</span><div class="redbot-platforms facebook"/>')
.appendTo(panelUrl);
$(panelUrl).RB_Platforms();
var panelEmail = $('<div class="panel panel-email" style="display:none;"/>').appendTo(container);
$('<div/>').css('marginTop','5px')
.append($('<div class="redbot-form-hint">Send user email associated to the Facebook Messenger account</div>'))
.appendTo(panelEmail);
var panelPhone = $('<div class="panel panel-phone" style="display:none;"/>').appendTo(container);
$('<div/>').css('marginTop','5px')
.append($('<div class="redbot-form-hint">Send user phone number associated to the Facebook Messenger account</div>'))
.appendTo(panelPhone);
var panelPostback = $('<div class="panel panel-postback" style="display:none;"/>').appendTo(container);
$('<div/>').css('marginTop','5px')
.append($('<input style="width:100%" class="node-input-rule-type" type="text" name="label" placeholder="Button label"/>'))
.appendTo(panelPostback);
$('<div/>').css('marginTop','5px')
.append($('<input style="width:100%" class="node-input-rule-type" type="text" name="value" placeholder="Postback value">'))
.appendTo(panelPostback);
var feedbackRow = $('<div/>').css('marginTop','5px')
.RB_hasPlatform(['telegram', 'slack'], options.platforms)
.append('<input class="node-input-rule-type" type="text" name="answer" style="width:60%;"placeholder="Button feedback (optional)"/>')
.append('<div class="redbot-platforms telegram slack"/>');
$('<input type="checkbox" name="alert" value="on" style="width: auto;margin:0px 10px 5px 10px;"/>')
.RB_hasPlatform(['telegram'], options.platforms)
.appendTo(feedbackRow);
$('<span>With popup</span><div class="redbot-platforms telegram"/>')
.RB_hasPlatform(['telegram'], options.platforms)
.appendTo(feedbackRow);
feedbackRow.appendTo(panelPostback);
$('<div/>').css('marginTop','5px')
.RB_hasPlatform('slack', options.platforms)
.append('<select name="style" style="width:70%">'
+ '<option value="">Select button style</option>'
+ '<option value="default">Default</option>'
+ '<option value="primary">Primary</option>'
+ '<option value="danger">Danger</option>'
+ '</select>')
.append('<div class="redbot-platforms slack"/>')
.appendTo(panelPostback);
$(panelPostback).RB_Platforms();
var panelDialog = $('<div class="panel panel-dialog" style="display:none;"/>').appendTo(container);
$('<div/>').css('marginTop','5px')
.append($('<input style="width:100%" class="node-input-rule-type" type="text" name="label" placeholder="Button label"/>'))
.appendTo(panelDialog);
$('<div/>').css('marginTop','5px')
.append($('<input style="width:100%" class="node-input-rule-type" type="text" name="value" placeholder="Dialog Id">'))
.appendTo(panelDialog);
$('<div/>').css('marginTop','5px')
.RB_hasPlatform(['telegram', 'slack'], options.platforms)
.append('<input class="node-input-rule-type" type="text" name="answer" placeholder="Button feedback (optional)"/>')
.appendTo(panelDialog);
$('<div/>').css('marginTop','5px')
.append('<select name="style" style="width:70%">'
+ '<option value="">Select button style</option>'
+ '<option value="default">Default</option>'
+ '<option value="primary">Primary</option>'
+ '<option value="danger">Danger</option>'
+ '</select>')
.appendTo(panelDialog);
var panelQuickReply = $('<div class="panel panel-quick-reply" style="display:none;"/>').appendTo(container);
$('<div/>').css('marginTop','5px')
.append($('<input style="width:100%" class="node-input-rule-type" type="text" name="label" placeholder="Button label"/>'))
.appendTo(panelQuickReply);
$('<div/>').css('marginTop','5px')
.append($('<input style="width:100%" class="node-input-rule-type" type="text" name="value" placeholder="Postback value">'))
.appendTo(panelQuickReply);
$('<div/>').css('marginTop','5px')
.append($('<input style="width:100%" class="node-input-rule-type" type="text" name="url" placeholder="Image URL"/>'))
.appendTo(panelQuickReply);
var panelCall = $('<div class="panel panel-call" style="display:none;"/>').appendTo(container);
$('<div/>').css('marginTop','5px')
.append($('<input style="width:100%" class="node-input-rule-type" type="text" name="label" placeholder="Button label"/>'))
.appendTo(panelCall);
$('<div/>').css('marginTop','5px')
.append($('<input style="width:100%" class="node-input-rule-type" type="text" name="number" placeholder="Phone number"/>'))
.appendTo(panelCall);
var panelNewline = $('<div class="panel panel-newline" style="display:none;"/>').appendTo(container);
$('<div/>').css('marginTop','5px')
.html('This creates a new row of buttons')
.appendTo(panelNewline);
var panelKeyboardButton = $('<div class="panel panel-keyboardButton" style="display:none;"/>').appendTo(container);
$('<div/>').css('marginTop','5px')
.append($('<input style="width:100%" class="node-input-rule-type" type="text" name="label" placeholder="Button label"/>'))
.appendTo(panelKeyboardButton);
$('<div class="panel panel-share" style="display:none;"/>').appendTo(container);
$('<div class="panel panel-logout" style="display:none;"/>').appendTo(container);
$('<div class="panel panel-location" style="display:none;"/>').appendTo(container);
var panelLogin = $('<div class="panel panel-login" style="display:none;"/>').appendTo(container);
$('<div/>').css('marginTop','5px')
.append($('<input style="width:100%" class="node-input-rule-type" type="text" name="url" placeholder="Authentication URL callback"/>'))
.appendTo(panelLogin);
return container;
};
$.fn.RB_mountElementDialog = function(options) {
options = options || {};
options.types = options.types != null ?
options.types : ['text', 'textarea', 'select'];
options.platforms = options.platforms != null ? options.platforms : ['slack'];
options.badges = options.badges !== false;
var container = $(this);
var main = $('<div/>').appendTo(container);
var cx = options.badges ? $.RedBot.platformClass : function() { return ''; };
var selectElementType = $('<select name="type"/>', {style:"width:200px; margin-left: 5px; text-align: center;"})
.attr('placeholder', 'Select element type')
.change(function() {
var type = $(this).val();
$('.panel', container).hide();
$('.panel-' + type, container).show();
// find the right button
var button = $.RedBot.buttonTypes.findButton(type);
// store class only if badges should be shown
if (button != null && options.badges) {
$(this).attr('class', button.className);
} else {
$(this).attr('class', '');
}
})
.appendTo(main);
selectElementType.append($('<option value="">Select element type</option>'));
$.RedBot.elementTypes.forEach(function(button) {
if (options.types.indexOf(button.type) !== -1 && $.RedBot.platforms(options.platforms, button.platforms)) {
selectElementType.append($('<option value="' + button.type + '">' + button.label + '</option>'));
}
});
var panelText = $('<div class="panel panel-text" style="display:none;"/>').appendTo(container);
$('<div/>').css('marginTop','5px')
.append($('<input style="width:100%" class="node-input-rule-type" type="text" name="label" placeholder="Label"/>'))
.appendTo(panelText);
$('<div/>').css('marginTop','5px')
.append($('<input style="width:100%" class="node-input-rule-type" type="text" name="name" placeholder="Name"/>'))
.appendTo(panelText);
$('<div/>').css('marginTop','5px')
.append($('<input style="width:100%" class="node-input-rule-type" type="text" name="value" placeholder="Initial value"/>'))
.appendTo(panelText);
$('<div/>').css('marginTop','5px')
.append($('<input style="width:100%" class="node-input-rule-type" type="text" name="placeholder" placeholder="Placeholder"/>'))
.appendTo(panelText);
$('<div/>').css('marginTop','5px')
.append($('<input style="width:100%" class="node-input-rule-type" type="text" name="hint" placeholder="Hint"/>'))
.appendTo(panelText);
$('<div/>').css('marginTop','5px')
.append('<select name="subtype" class="' + cx('select', ['']) + '" style="width:60%">'
+ '<option value="">Select sub-type</option>'
+ '<option value="email">Email</option>'
+ '<option value="number">Number</option>'
+ '<option value="tel">Telephone</option>'
+ '<option value="url">URL</option>'
+ '</select>')
.append('<input type="checkbox" name="optional" value="on" style="width: auto;margin:0px 10px 5px 10px;"/>')
.append('<span>Optional</span>')
.appendTo(panelText);
$('<div/>').css('marginTop','5px')
.append($('<input style="width:45%" class="node-input-rule-type" type="number" name="min_length" placeholder="Min Length"/>'))
.append($('<input style="width:45%;margin-left: 10%" class="node-input-rule-type" type="number" name="max_length" placeholder="Max Length"/>'))
.appendTo(panelText);
var panelTextarea = $('<div class="panel panel-textarea" style="display:none;"/>').appendTo(container);
$('<div/>').css('marginTop','5px')
.append($('<input style="width:100%" class="node-input-rule-type" type="text" name="label" placeholder="Label"/>'))
.appendTo(panelTextarea);
$('<div/>').css('marginTop','5px')
.append($('<input style="width:100%" class="node-input-rule-type" type="text" name="name" placeholder="Name"/>'))
.appendTo(panelTextarea);
$('<div/>').css('marginTop','5px')
.append($('<input style="width:100%" class="node-input-rule-type" type="text" name="value" placeholder="Initial value"/>'))
.appendTo(panelTextarea);
$('<div/>').css('marginTop','5px')
.append($('<input style="width:100%" class="node-input-rule-type" type="text" name="placeholder" placeholder="Placeholder"/>'))
.appendTo(panelTextarea);
$('<div/>').css('marginTop','5px')
.append($('<input style="width:100%" class="node-input-rule-type" type="text" name="hint" placeholder="Hint"/>'))
.appendTo(panelTextarea);
$('<div/>').css('marginTop','5px')
.append('<select name="subtype" class="' + cx('select', ['']) + '" style="width:60%">'
+ '<option value="">Subtype</option>'
+ '<option value="email">Email</option>'
+ '<option value="number">Number</option>'
+ '<option value="tel">Telephone</option>'
+ '<option value="url">URL</option>'
+ '</select>')
.append('<input type="checkbox" name="optional" value="on" style="width: auto;margin:0px 10px 5px 10px;"/>')
.append('<span>Optional</span>')
.appendTo(panelTextarea);
var panelSelect = $('<div class="panel panel-select" style="display:none;"/>').appendTo(container);
$('<div/>').css('marginTop','5px')
.append($('<input style="width:100%" class="node-input-rule-type" type="text" name="label" placeholder="Label"/>'))
.appendTo(panelSelect);
$('<div/>').css('marginTop','5px')
.append($('<input style="width:100%" class="node-input-rule-type" type="text" name="name" placeholder="Name"/>'))
.appendTo(panelSelect);
$('<div/>').css('marginTop','5px')
.append($('<input style="width:100%" class="node-input-rule-type" type="text" name="value" placeholder="Initial value"/>'))
.appendTo(panelSelect);
$('<div/>').css('marginTop','5px')
.append($('<input style="width:100%" class="node-input-rule-type" type="text" name="placeholder" placeholder="Placeholder"/>'))
.appendTo(panelSelect);
$('<div/>').css('marginTop','5px')
.append($('<input style="width:100%" class="node-input-rule-type" type="text" name="hint" placeholder="Hint"/>'))
.appendTo(panelSelect);
$('<div/>').css('marginTop','5px')
.append('<div class="container-options"/>')
.appendTo(panelSelect);
panelSelect.find('.container-options').RB_OptionsEditor({ label: 'Combo box options'});
};
$.RedBot.registerType('chatbot-inline-buttons', {
category: $.RedBot.config.name,
color: '#FFCC66',
defaults: {
name: {
value: ''
},
buttons: {
value: [],
validate: function(buttons) {
if (buttons == null) {
return true; // allow no buttons
}
var valid = true;
var idx;
for(idx = 0; idx < buttons.length; idx++) {
if (!$.RedBot.validate.button(buttons[idx])) {
valid = false;
}
}
return valid;
}
},
message: {
value: ''
},
trackMessage: {
value: false
},
outputs: {
value: 1
}
},
inputs: 1,
outputs: 1,
outputLabels: function(index) {
if (index === 0) {
return 'to sender node';
} else {
const button = this.buttons[index - 1];
if (button.type === 'postback') {
if (button.label != null && button.label !== '') {
return button.label + (button.value != null && button.value !== '' ? ' (' + button.value + ')' : '');
} else if (button.value != null && button.value !== '') {
return button.value;
}
}
return 'not used';
}
},
paletteLabel: 'Buttons',
icon: 'chatbot-inline-button.png',
label: function() {
return this.name || 'Buttons';
},
oneditsave: function() {
var buttons = $("#node-input-buttons-container").editableList('items');
var node = this;
node.buttons = [];
var idx;
for(idx = 0; idx < buttons.length; idx++) {
node.buttons.push($(buttons[idx]).RB_getButtonData());
}
// store outputs
if ($('#node-input-trackMessage').is(':checked')) {
node.outputs = node.buttons.length + 2;
} else {
node.outputs = 1;
}
},
oneditprepare: function() {
var node = this;
$('#node-input-buttons-container')
.css('min-height','300px')
.css('min-width','450px')
.editableList({
addButton: 'Add button',
addItem: function(container, i, item) {
$(container).RB_mountButtonDialog({
types: ['url', 'postback', 'call', 'login', 'newline', 'logout', 'dialog'],
platforms: ['facebook', 'telegram', 'slack', 'msteams']
});
$(container).RB_setButtonData(item);
},
removable: true,
sortable: true
});
$.RedBot.fetchPlatforms()
.done(function() {
var buttons = node.buttons;
var idx;
for (idx = 0; idx < buttons.length; idx++) {
$('#node-input-buttons-container').editableList('addItem', buttons[idx]);
}
});
},
oneditresize: function() {
var dialogForm = $('#dialog-form');
var rowName = $('.form-row-name', dialogForm);
var rowMessage = $('.form-row-message', dialogForm);
var rowLabel = $('.form-row-label', dialogForm);
var rowHint = $('.form-row-hint', dialogForm);
var rowTrack = $('.form-row-track', dialogForm);
var height = dialogForm.height()
- rowTrack.height()
- rowName.height()
- rowMessage.height()
- rowLabel.height()
- rowHint.height()
- 30;
$('#node-input-buttons-container').editableList('height', height);
}
});
</script>
<script type="text/x-red" data-template-name="chatbot-inline-buttons">
<div class="form-row form-row-name">
<label for="node-input-name"><i class="icon-tag"></i> Name</label>
<input type="text" id="node-input-name" placeholder="Name">
</div>
<div class="form-row form-row-message">
<label for="node-input-message"><i class="icon-envelope"></i> Message</label>
<textarea id="node-input-message" placeholder="Message" style="width:93%;height:50px;"></textarea>
<div style="max-width: 460px;font-size: 12px;color: #999999;line-height: 14px;clear:both;margin-top:5px;">
Supports handlebars-like variables for chat context like {{firstName}}, {{lastName}}, etc. and emoticons (:smile:, etc.)
</div>
</div>
<div class="form-row form-row-label" style="margin-bottom:0;">
<label><i class="fa fa-list"></i> <span>Buttons</span></label>
</div>
<div class="form-row node-input-rule-container-row">
<ol id="node-input-buttons-container"></ol>
</div>
<div class="form-row form-row-track">
<label for="node-input-trackMessage">Track</label>
<input type="checkbox" value="true" id="node-input-trackMessage" style="width:auto">
<span class="redbot-form-hint">
Track answers to these buttons here (will enable an output pin for each button)
</span>
</div>
</script>
<script type="text/x-red" data-help-name="chatbot-inline-buttons"><p>This node creates a message with one or more buttons in order to get a quick reaction from the users. </p>
<p>Available buttons: </p>
<ul>
<li><p><strong>URL</strong>: Open a URL inside the client. Button feedbacks are available for Telegram and Messenger extensions in Facebook <em>[Telegram, Facebook, Viber]</em></p>
</li>
<li><p><strong>Postback</strong>: Allow the user to send a predefined message, the message will no be shown in the chat history. Button feedbacks are available for Telegram and Messenger extensions in Facebook <em>[Telegram, Facebook, Smooch, Viber]</em></p>
</li>
<li><p><strong>Phone call</strong>: Starts a phone call on mobile. <em>[Facebook]</em></p>
</li>
<li><p><strong>Log In</strong>: Starts the account linking flow. <em>[Facebook]</em></p>
</li>
<li><p><strong>Log Out</strong>: Starts the account unlinking flow. <em>[Facebook]</em></p>
</li>
<li><p><strong>New row</strong>: Telegram supports buttons layout with multiple row, this element just starts a new one. <em>[Telegram, Viber]</em></p>
</li>
</ul>
<p>Platform exceptions: </p>
<ul>
<li><p><strong>Telegram</strong> supports a visual feedback, visible in the client, when a <code>Postback</code> or <code>URL</code> buttons is pressed</p>
</li>
<li><p><strong>Facebook</strong> supports some extra parameters in the <code>URL</code> button, like the size of the web view and <a href="https://developers.facebook.com/docs/messenger-platform/webview">messenger extensions</a> and a maximum od three buttons.</p>
</li>
</ul>
<p>The tipical use of the buttons node is with the <em>Track</em> option of a <code>Sender node</code> and <a href="https://www.notion.so/4113636f565d4ff4af08bc61a644206b">Rules node</a> to capture the aswer</p>
<p><img src="https://s3.us-west-2.amazonaws.com/secure.notion-static.com/56c82cb6-1c83-41c9-8ec0-2c43c4a912c6/buttons-legacy.png?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Content-Sha256=UNSIGNED-PAYLOAD&X-Amz-Credential=AKIAT73L2G45EIPT3X45%2F20230218%2Fus-west-2%2Fs3%2Faws4_request&X-Amz-Date=20230218T124941Z&X-Amz-Expires=3600&X-Amz-Signature=c96ded70d378c3cdc5ea57d43d0132f95deb061ef78f35e3b9fa5f05294eb6f9&X-Amz-SignedHeaders=host&x-id=GetObject" alt="Track answer in the Sender node"></p>
<p>In this example the <code>Buttons node</code> includes two postback buttons wiht a <em>label</em> (it’s the label of the button) and a <em>value</em> (it’s what will be sent back to the chatbot if clicked). The values can be anything but it’s a good habit to use Telegram-like commands, i.e. <code>/option1</code> and <code>/option2</code>, the reason for this is that they don’t interfere with user-generated sentences and can be easily filtered by a <a href="https://www.notion.so/4113636f565d4ff4af08bc61a644206b">Rules node</a>.
The <code>Sender node</code> uses the Track option, the answer will be captured and sent to the Rules node which can capture one of the possible answers with a rule <em>“Message is command …”.</em></p>
<p>The <em>“Track message”</em> option enables a more readable layout to handle user’s answers:</p>
<p><img src="https://s3.us-west-2.amazonaws.com/secure.notion-static.com/3b7a7638-a5ba-4316-8203-0ae783657941/buttons-new.png?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Content-Sha256=UNSIGNED-PAYLOAD&X-Amz-Credential=AKIAT73L2G45EIPT3X45%2F20230218%2Fus-west-2%2Fs3%2Faws4_request&X-Amz-Date=20230218T124941Z&X-Amz-Expires=3600&X-Amz-Signature=f9195054be758bf754e6985bcd3fd0bc280830972f9cc34e4eb7e06490b93481&X-Amz-SignedHeaders=host&x-id=GetObject" alt="Track answer in the Buttons node"></p>
<p>In that case the user’s answer will be tracked directly by the <code>Buttons node</code> through one of the outputs related the postback buttons (hover on the outputs to know the output details).
The first pin of the <code>Buttons node</code> is always to be connected to a <code>Sender node</code> while the last pin is the fallback (in case the user, for example, writes something instead of clicking the buttons). </p>
<p>Buttons can be created programmatically by an upstream <code>Function node</code> passing array of buttons in the message payload:</p>
<pre><code class="language-javascript">msg.payload = {
message: 'This is a message above the buttons',
buttons: [
{
type: 'url',
url: 'http://javascript-jedi.com',
label: 'Javascript Jedi'
},
{
type: 'postback',
value: 'MY_POSTBACK_MESSAGE',
label: 'Click me!'
},
{
type: 'share'
}
]
};
return msg;
</code></pre>
<p>Available parameters for the <code>msg.payload</code></p>
<table>
<thead>
<tr>
<th>Name</th>
<th>Type</th>
<th>Description</th>
</tr>
</thead>
<tbody><tr>
<td>message</td>
<td>string</td>
<td>The message text above the buttons</td>
</tr>
<tr>
<td>buttons</td>
<td>array of [button]</td>
<td>The list of inline buttons</td>
</tr>
<tr>
<td>trackMessage</td>
<td>boolean</td>
<td>Track the answer message in the <code>Buttons node</code>, the answer will be redirected to one of output pins related to the buttons. Default is <code>false</code>.</td>
</tr>
</tbody></table>
<p>The <code>[button]</code> object</p>
<table>
<thead>
<tr>
<th>Name</th>
<th>Type</th>
<th>Description</th>
</tr>
</thead>
<tbody><tr>
<td>type</td>
<td>string</td>
<td>Type of button: <em>url</em>, <em>postback</em>, <em>quick-reply</em>, <em>location</em>, <em>call</em>, <em>share</em>, <em>login</em>, <em>logout</em>, <em>newline</em></td>
</tr>
<tr>
<td>label</td>
<td>string</td>
<td>Label of the button</td>
</tr>
<tr>
<td>value</td>
<td>string</td>
<td>Value returned as payload in <code>postback</code> buttons</td>
</tr>
<tr>
<td>url</td>
<td>string</td>
<td>Url to redirect to for <code>url</code> buttons or authentication URL for <code>login</code> buttons</td>
</tr>
<tr>
<td>number</td>
<td>string</td>
<td>Phone number to call for <code>call</code> buttons</td>
</tr>
<tr>
<td>messengerExtensions</td>
<td>boolean</td>
<td>Include Messenger Extensions for <code>url</code> buttons</td>
</tr>
<tr>
<td>answer</td>
<td>string</td>
<td>The feedback shown on Telegram client for <code>url</code> and <code>postback</code> buttons</td>
</tr>
<tr>
<td>alert</td>
<td>boolean</td>
<td>Show the feedback as alert on Telegram client for <code>url</code> and <code>postback</code> buttons</td>
</tr>
<tr>
<td>style</td>
<td>string</td>
<td>Style of buttons in Slack: <em>default</em>, <em>primary</em>, <em>danger</em></td>
</tr>
<tr>
<td>webViewHeightRatio</td>
<td>string</td>
<td>Aspect ratio of the webview in Facebook Messenger for <code>url buttons</code>. Valid values: <em>tall</em>, <em>compact</em>, <em>full</em></td>
</tr>
</tbody></table>
</script>
<style>
.form-row-checkbox {
margin-bottom: 0px;
}
.form-row-checkbox input[type=checkbox] {
width: auto;
margin-top: 0px;
margin-right: 5px;
}
.icon-platform-telegram {
display: inline-block;
width: 9px;
height: 9px;
background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAkAAAAJCAYAAADgkQYQAAAAAXNSR0IArs4c6QAAADRJREFUGBlj1F764D8DAcACk78SJQ9jwmmdZQ/BbLgimABIMYwNU80EY+Cjh4QidJ+BPAQAUcEMK/ZfXe8AAAAASUVORK5CYII=);
margin-left: 3px;
margin-right: 3px;
vertical-align: middle;
}
.icon-platform-discord {
display: inline-block;
width: 9px;
height: 9px;
background: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAkAAAAJCAYAAADgkQYQAAAAAXNSR0IArs4c6QAAADxJREFUGBljVFPT+s9AALDA5G/evApjgml1dW04H64IJIIsAdIE4zPBleNh0FkRisORfQhzNMipjMSEEwBROQx6SDYaygAAAABJRU5ErkJggg==');
margin-left: 3px;
margin-right: 3px;
vertical-align: middle;
}
.icon-platform-facebook {
display: inline-block;
width: 9px;
height: 9px;
background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAkAAAAJCAYAAADgkQYQAAAAAXNSR0IArs4c6QAAAEJJREFUGBljtIqc8Z+BAGCByR9dlg5jwmnrqJlgNlwRiAcThKuCMpjQBbDxUUxCthLZVBRFyBLIJhJlHVGKGIkJJwAbVQzJXzC/gwAAAABJRU5ErkJggg==);
margin-left: 3px;
margin-right: 3px;
vertical-align: middle;
}
.icon-platform-smooch {
display: inline-block;
width: 9px;
height: 9px;
background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAkAAAAJCAYAAADgkQYQAAAAAXNSR0IArs4c6QAAAENJREFUGBljXOyx/T8DAcAEk4/Z7gFjgmlkPlwRSAYmAaNhulAULfHcAVYIopEBiiKQBLoCkBiGIpAgOqCeIkZiwgkAEPoRCUXTyWoAAAAASUVORK5CYII=);
margin-left: 3px;
margin-right: 3px;
vertical-align: middle;
}
.icon-platform-slack {
display: inline-block;
width: 9px;
height: 9px;
background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAkAAAAJCAYAAADgkQYQAAAAAXNSR0IArs4c6QAAAEtJREFUGBljDNvW/Z+BAGBBll/pWYLMZQjf3gPmwxWBFMAEUVQCOUzoAtj4cJNApiBbh2wqXBHIBGQJZOtJsw7ZKnRT4dYhW4XueACZqRaCOTsvfwAAAABJRU5ErkJggg==);
margin-left: 3px;
margin-right: 3px;
vertical-align: middle;
}
.icon-platform-viber {
display: inline-block;
width: 9px;
height: 9px;
background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAkAAAAJCAIAAABv85FHAAAANklEQVQImWNsKL/MgAMwQaj6Dh24EJzNhEsT5XKNFVcg1tR36DRWXCHFTIhWuCZ0fcgSDAwMAO+nENww2Up1AAAAAElFTkSuQmCC);
margin-left: 3px;
margin-right: 3px;
vertical-align: middle;
}
.icon-platform-universal {
display: inline-block;
width: 9px;
height: 9px;
background: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAkAAAAJCAIAAABv85FHAAAAKUlEQVQImWP8v4MBF2CCUP/d/8OF4GwmnLroL8cI9wPceYw7GdHlMAEAfGIMv3ninmsAAAAASUVORK5CYII=');
margin-left: 3px;
margin-right: 3px;
vertical-align: middle;
}
.icon-platform-twilio {
display: inline-block;
width: 9px;
height: 9px;
background: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAkAAAAJCAYAAADgkQYQAAAAAXNSR0IArs4c6QAAADNJREFUGBljfGfk9Z+BAGCByQue3Qpjwun3xt5gNiO6SSDFMEmYaiYYAx89GBVh+A6bBwDzEA1NPYkyaAAAAABJRU5ErkJggg==');
margin-left: 3px;
margin-right: 3px;
vertical-align: middle;
}
.icon-platform-alexa {
display: inline-block;
width: 9px;
height: 9px;
background: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAkAAAAJCAYAAADgkQYQAAAAAXNSR0IArs4c6QAAAEJJREFUGBljVD799z8DAcCCLH/HhAnOVTnzD86GKwIpQJZA5iO0wvVhMuAmgaSQrUNWiqII3TqYQqKsI0oRIzHhBABD+hL/gIpxvwAAAABJRU5ErkJggg==');
margin-left: 3px;
margin-right: 3px;
vertical-align: middle;
}
.platform-facebook {
background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAkAAAAJCAYAAADgkQYQAAAAAXNSR0IArs4c6QAAAEJJREFUGBljtIqc8Z+BAGCByR9dlg5jwmnrqJlgNlwRiAcThKuCMpjQBbDxUUxCthLZVBRFyBLIJhJlHVGKGIkJJwAbVQzJXzC/gwAAAABJRU5ErkJggg==);
background-position: right 2px top 2px;
background-repeat: no-repeat;
}
.platform-combo-facebook {
background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAkAAAAJCAYAAADgkQYQAAAAAXNSR0IArs4c6QAAAEJJREFUGBljtIqc8Z+BAGCByR9dlg5jwmnrqJlgNlwRiAcThKuCMpjQBbDxUUxCthLZVBRFyBLIJhJlHVGKGIkJJwAbVQzJXzC/gwAAAABJRU5ErkJggg==);
background-position: right 12px top 2px;
background-repeat: no-repeat;
}
.platform-telegram {
background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAkAAAAJCAYAAADgkQYQAAAAAXNSR0IArs4c6QAAADRJREFUGBlj1F764D8DAcACk78SJQ9jwmmdZQ/BbLgimABIMYwNU80EY+Cjh4QidJ+BPAQAUcEMK/ZfXe8AAAAASUVORK5CYII=);
background-position: right 2px top 2px;
background-repeat: no-repeat;
}
.platform-combo-telegram {
background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAkAAAAJCAYAAADgkQYQAAAAAXNSR0IArs4c6QAAADRJREFUGBlj1F764D8DAcACk78SJQ9jwmmdZQ/BbLgimABIMYwNU80EY+Cjh4QidJ+BPAQAUcEMK/ZfXe8AAAAASUVORK5CYII=);
background-position: right 12px top 2px;
background-repeat: no-repeat;
}
.platform-combo-slack {
background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAkAAAAJCAYAAADgkQYQAAAAAXNSR0IArs4c6QAAAEtJREFUGBljDNvW/Z+BAGBBll/pWYLMZQjf3gPmwxWBFMAEUVQCOUzoAtj4cJNApiBbh2wqXBHIBGQJZOtJsw7ZKnRT4dYhW4XueACZqRaCOTsvfwAAAABJRU5ErkJggg==);
background-position: right 12px top 2px;
background-repeat: no-repeat;
}
.platform-smooch {
background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAkAAAAJCAYAAADgkQYQAAAAAXNSR0IArs4c6QAAAENJREFUGBljXOyx/T8DAcAEk4/Z7gFjgmlkPlwRSAYmAaNhulAULfHcAVYIopEBiiKQBLoCkBiGIpAgOqCeIkZiwgkAEPoRCUXTyWoAAAAASUVORK5CYII=);
background-position: right 2px top 2px;
background-repeat: no-repeat;
}
.platform-combo-alexa {
background: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAkAAAAJCAYAAADgkQYQAAAAAXNSR0IArs4c6QAAAEJJREFUGBljVD799z8DAcCCLH/HhAnOVTnzD86GKwIpQJZA5iO0wvVhMuAmgaSQrUNWiqII3TqYQqKsI0oRIzHhBABD+hL/gIpxvwAAAABJRU5ErkJggg==');
background-position: right 12px top 2px;
background-repeat: no-repeat;
}
.platform-combo-smooch {
background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAkAAAAJCAYAAADgkQYQAAAAAXNSR0IArs4c6QAAAENJREFUGBljXOyx/T8DAcAEk4/Z7gFjgmlkPlwRSAYmAaNhulAULfHcAVYIopEBiiKQBLoCkBiGIpAgOqCeIkZiwgkAEPoRCUXTyWoAAAAASUVORK5CYII=);
background-position: right 12px top 2px;
background-repeat: no-repeat;
}
.platform-telegram-facebook, .platform-facebook-telegram {
background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAkAAAAJCAYAAADgkQYQAAAAAXNSR0IArs4c6QAAADRJREFUGBlj1F764D8DAcACk78SJQ9jwmmdZQ/BbLgimABIMYwNU80EY+Cjh4QidJ+BPAQAUcEMK/ZfXe8AAAAASUVORK5CYII=),
url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAkAAAAJCAYAAADgkQYQAAAAAXNSR0IArs4c6QAAAEJJREFUGBljtIqc8Z+BAGCByR9dlg5jwmnrqJlgNlwRiAcThKuCMpjQBbDxUUxCthLZVBRFyBLIJhJlHVGKGIkJJwAbVQzJXzC/gwAAAABJRU5ErkJggg==);
background-position: right 2px top 2px, right 12px top 2px;
background-repeat: no-repeat, no-repeat;
}
.platform-combo-telegram-facebook, .platform-combo-facebook-telegram {
background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAkAAAAJCAYAAADgkQYQAAAAAXNSR0IArs4c6QAAADRJREFUGBlj1F764D8DAcACk78SJQ9jwmmdZQ/BbLgimABIMYwNU80EY+Cjh4QidJ+BPAQAUcEMK/ZfXe8AAAAASUVORK5CYII=),
url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAkAAAAJCAYAAADgkQYQAAAAAXNSR0IArs4c6QAAAEJJREFUGBljtIqc8Z+BAGCByR9dlg5jwmnrqJlgNlwRiAcThKuCMpjQBbDxUUxCthLZVBRFyBLIJhJlHVGKGIkJJwAbVQzJXzC/gwAAAABJRU5ErkJggg==);
background-position: right 12px top 2px, right 22px top 2px;
background-repeat: no-repeat, no-repeat;
}
.platform-combo-telegram-facebook-viber {
background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAkAAAAJCAYAAADgkQYQAAAAAXNSR0IArs4c6QAAADRJREFUGBlj1F764D8DAcACk78SJQ9jwmmdZQ/BbLgimABIMYwNU80EY+Cjh4QidJ+BPAQAUcEMK/ZfXe8AAAAASUVORK5CYII=),
url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAkAAAAJCAYAAADgkQYQAAAAAXNSR0IArs4c6QAAAEJJREFUGBljtIqc8Z+BAGCByR9dlg5jwmnrqJlgNlwRiAcThKuCMpjQBbDxUUxCthLZVBRFyBLIJhJlHVGKGIkJJwAbVQzJXzC/gwAAAABJRU5ErkJggg==),
url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAkAAAAJCAIAAABv85FHAAAANklEQVQImWNsKL/MgAMwQaj6Dh24EJzNhEsT5XKNFVcg1tR36DRWXCHFTIhWuCZ0fcgSDAwMAO+nENww2Up1AAAAAElFTkSuQmCC);
background-position: right 12px top 2px, right 22px top 2px, right 32px top 2px;
background-repeat: no-repeat, no-repeat;
}
.platform-telegram-slack, platform-slack-telegram {
background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAkAAAAJCAYAAADgkQYQAAAAAXNSR0IArs4c6QAAADRJREFUGBlj1F764D8DAcACk78SJQ9jwmmdZQ/BbLgimABIMYwNU80EY+Cjh4QidJ+BPAQAUcEMK/ZfXe8AAAAASUVORK5CYII=),
url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAkAAAAJCAYAAADgkQYQAAAAAXNSR0IArs4c6QAAAEtJREFUGBljDNvW/Z+BAGBBll/pWYLMZQjf3gPmwxWBFMAEUVQCOUzoAtj4cJNApiBbh2wqXBHIBGQJZOtJsw7ZKnRT4dYhW4XueACZqRaCOTsvfwAAAABJRU5ErkJggg==);
background-position: right 2px top 2px, right 12px top 2px;
background-repeat: no-repeat, no-repeat;
}
.platform-telegram-slack-viber {
background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAkAAAAJCAYAAADgkQYQAAAAAXNSR0IArs4c6QAAADRJREFUGBlj1F764D8DAcACk78SJQ9jwmmdZQ/BbLgimABIMYwNU80EY+Cjh4QidJ+BPAQAUcEMK/ZfXe8AAAAASUVORK5CYII=),
url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAkAAAAJCAYAAADgkQYQAAAAAXNSR0IArs4c6QAAAEtJREFUGBljDNvW/Z+BAGBBll/pWYLMZQjf3gPmwxWBFMAEUVQCOUzoAtj4cJNApiBbh2wqXBHIBGQJZOtJsw7ZKnRT4dYhW4XueACZqRaCOTsvfwAAAABJRU5ErkJggg==),
url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAkAAAAJCAIAAABv85FHAAAANklEQVQImWNsKL/MgAMwQaj6Dh24EJzNhEsT5XKNFVcg1tR36DRWXCHFTIhWuCZ0fcgSDAwMAO+nENww2Up1AAAAAElFTkSuQmCC);
background-position: right 2px top 2px, right 12px top 2px, right 22px top 2px;
background-repeat: no-repeat, no-repeat;
}
.platform-combo-telegram-slack {
background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAkAAAAJCAYAAADgkQYQAAAAAXNSR0IArs4c6QAAADRJREFUGBlj1F764D8DAcACk78SJQ9jwmmdZQ/BbLgimABIMYwNU80EY+Cjh4QidJ+BPAQAUcEMK/ZfXe8AAAAASUVORK5CYII=),
url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAkAAAAJCAYAAADgkQYQAAAAAXNSR0IArs4c6QAAAEtJREFUGBljDNvW/Z+BAGBBll/pWYLMZQjf3gPmwxWBFMAEUVQCOUzoAtj4cJNApiBbh2wqXBHIBGQJZOtJsw7ZKnRT4dYhW4XueACZqRaCOTsvfwAAAABJRU5ErkJggg==);
background-position: right 12px top 2px, right 22px top 2px;
background-repeat: no-repeat, no-repeat;
}
.platform-combo-telegram-viber {
background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAkAAAAJCAYAAADgkQYQAAAAAXNSR0IArs4c6QAAADRJREFUGBlj1F764D8DAcACk78SJQ9jwmmdZQ/BbLgimABIMYwNU80EY+Cjh4QidJ+BPAQAUcEMK/ZfXe8AAAAASUVORK5CYII=),
url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAkAAAAJCAIAAABv85FHAAAANklEQVQImWNsKL/MgAMwQaj6Dh24EJzNhEsT5XKNFVcg1tR36DRWXCHFTIhWuCZ0fcgSDAwMAO+nENww2Up1AAAAAElFTkSuQmCC);
background-position: right 12px top 2px, right 22px top 2px;
background-repeat: no-repeat, no-repeat;
}
.platform-smooch-facebook, .platform-facebook-smooch {
background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAkAAAAJCAYAAADgkQYQAAAAAXNSR0IArs4c6QAAAENJREFUGBljXOyx/T8DAcAEk4/Z7gFjgmlkPlwRSAYmAaNhulAULfHcAVYIopEBiiKQBLoCkBiGIpAgOqCeIkZiwgkAEPoRCUXTyWoAAAAASUVORK5CYII=),
url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAkAAAAJCAYAAADgkQYQAAAAAXNSR0IArs4c6QAAAEJJREFUGBljtIqc8Z+BAGCByR9dlg5jwmnrqJlgNlwRiAcThKuCMpjQBbDxUUxCthLZVBRFyBLIJhJlH