Stickers and Gif cause Facebook Messenger bot to freeze - node.js

The Facebook Messenger API is pretty sweet overall. However, whenever an user sends a sticker (The balloon thumb up sticker for example) to my bot, it always freezes for around 20 seconds. If the user sends a lot of stickers, the bot will simply crash and Facebook will send me "Webhook failing" developer alert.
I suspect there is something wrong with my code but I couldn't find any error. Something interesting I found is that when the bot crashed and Facebook sends me the "Webhook failing" alert, the bot will be revived and back to responding to messages if I resubscribe my app to the page by entering the following in the command line.
curl -X POST "https://graph.facebook.com/v2.6/me/subscribed_apps?access_token=<PAGE_ACCESS_TOKEN>"
Here is some information that may be helpful to you.
Repo: https://github.com/lorix-lpan/r-score-god
Server.js: https://github.com/lorix-lpan/r-score-god/blob/master/src/server.js
Facebook Page: https://www.facebook.com/rscoregod/
Note: The bot is still not available to the public at the moment, message it so I can add you as a test user.
Thank you very much!

Eventually, I figured out the problem myself. There is indeed something wrong with my code (or facebook's getting started code ;) ).
From Messenger platform's getting started page
The post handler is defined as the following
app.post('/webhook/', function (req, res) {
messaging_events = req.body.entry[0].messaging;
for (i = 0; i < messaging_events.length; i++) {
event = req.body.entry[0].messaging[i];
sender = event.sender.id;
if (event.message && event.message.text) {
text = event.message.text;
sendTextMessage(sender, "Text received, echo: "+ text.substring(0, 200));
}
}
res.sendStatus(200);
});
However, when a sticker or GIF is sent to the server, the "message" field of the "event" variable will be empty. Thus, the code inside the following block will not be evaluated and no HTTP request will be made since the sendTextMessage function POST to the Facebook server.
if (event.message && event.message.text) {
text = event.message.text;
sendTextMessage(sender, "Text received, echo: "+ text.substring(0, 200));
}
I solved the issue by simply adding another simple if statement for stickers and GIF (or other attachments). When an attachment is sent by the user (either a GIF or a sticker), the "event" variable will have a "attachments" property. In other words, event.attachments will be defined. My solution is the following:
app.post('/webhook/', function (req, res) {
messaging_events = req.body.entry[0].messaging;
for (i = 0; i < messaging_events.length; i++) {
event = req.body.entry[0].messaging[i];
sender = event.sender.id;
if (event.attachments) {
sendTextMessage(sender, 'I am an attachment');
}
if (event.message && event.message.text) {
text = event.message.text;
sendTextMessage(sender, "Text received, echo: "+ text.substring(0, 200));
}
}
res.sendStatus(200);
});
Check out this commit for more detail

Related

Can't send image with Slackbot using slackbots (javascript)

I'm using slackbots (https://github.com/mishk0/slack-bot-api) to create an interactive bot.
I can, as a user, send message in chat and having my bot giving me an answer depending on what i wrote. Like if I type : !weekend, my bot will answer if weekend is close or not by fetching an API.
It's working this way
bot.on('message', data => {
if (data.type !== 'message') {
return;
}
handleMessage(data.text);
});
function handleMessage(message) {
switch (message) {
case '!weekend':
case '!we':
fetchWeekendData();
break;
case '!apero':
case '!biere':
case '!pastis':
fetchAperoData();
break;
case '!meteo':
fetchWeatherData();
break;
case '!metro':
fetchMetroData('A');
fetchMetroData('R');
break;
case '!features':
getFeatures();
break;
}
}
function fetchWeekendData() {
axios.get('https://estcequecestbientotleweekend.fr/api',
).then(res => {
const weText = res.data.text;
postToChannel(`_Bientôt le week end ?_ : *${weText}*`);
});
}
function postToChannel(message) {
bot.postMessageToChannel(
'général',
message,
params
)
}
I have another function calling, this time, a weather api. The api respond with many infos and
a link to a png depending on the weather. A little weather icon.
Problem is, when i send back my message to chat, it send the image link and i just can't figure out how to get this link as an image in chat.
function fetchWeatherData() {
axios.get('http://api.weatherstack.com/current?access_key=myAPIkey&query=Paris&units=m',
).then(res => {
const location = res.data.location.name;
const icon = res.data.current.weather_icons;
const temperature = res.data.current.temperature;
const feelslike = res.data.current.feelslike;
const humidity = res.data.current.humidity;
postToChannel(`Météo à *${location}* : ${icon} \n>_Température_ : *${temperature}* °C _Ressenti_ : *${feelslike}* °C\n\n>_Humidité_ : *${humidity}* %`)
});
}
If anyone has already used slack-bot-api and posted images with his bot, I'd like to know how you did this cause I'm running out of idea, slack api docs is showing JSON attachments for images but I don't know how to use it with this package.
EDIT : Alright it's solved, this way
function postToChannelWithImage() {
bot.postMessageToChannel(
'général',
'yikes itis working',
params = {
"icon_url": "https://avatars.slack-edge.com/2020-02-04/935676215584_38623245747b942874b5_192.jpg",
"attachments":
[
{
"fallback": "this did not work",
"image_url": "https://a.slack-edge.com/80588/img/blocks/bkb_template_images/beagle.png"
}
]
}
)
}
I added the array and it worked perfectly, I just have to add other params into the same array to keep my config the way it is.
Thanks a lot to #Erik Kalkoken !!
This library seams to just forward parameters to the respective Slack API method, which is chat.postMessage.
To post an image with Slack you need to include an image URL either within an attachment (outmoded) or blocks.
e.g. to attach an image wit attachments you would add this array via params:
{
"attachments":
[
{
"fallback": "this did not work",
"image_url": "https://a.slack-edge.com/80588/img/blocks/bkb_template_images/beagle.png"
}
]
}

Show warning message when sending email

I would like to display a warning message when sending a email. And only send after the user click on dismiss.
I set the persistent to true on notificationMessages.
But when sending the email, the message will be quickly shown but the email will be sent straight away without me having a chance to read the message.
Any idea what could I do?
Office.context.mailbox.item.notificationMessages.addAsync("cost_warning", {
type: "informationalMessage",
message: "message",
icon : "iconid",
persistent: true
});
event.completed({ allowEvent: true });
You can achieve this by using NotificationMessage.getAllAsync API.
Just set up an interval using setInterval and wait till notificationMessage.getAllAsync() stops returning your notification, then call
event.completed({ allowEvent: true });
But
I would recommend you to use a dialog API and display a webpage with the necessary information instead of using a notification message.
Notification messages are not meant for blocking information, dialog is more appropriate in this scenario.
Edit:
// Add your notification message
var interval = window.setInterval(checkNotificationMessages, 2000);
function checkNotificationMessages() {
Office.context.mailbox.item.notificationMessages.getAllAsync(
function (asyncResult) {
if (asyncResult.status != "failed") {
if (asyncResult.value.length == 0 ) {
window.clearInterval(interval);
// Perform some action and decide whether to allow/block send
}
}
}
);
}

Telegram Bot API. How to collect images only between start and end messages?

I'm writing Telegram bot (nodejs) which will collect all images sent to it between "start" and "end" messages. I learned how to start bot.onText(/\/start/, but how to react on "end" message from user to start reacting after that?
You need to maintain state for every user who is going to send you the /start and /end command. You can persist the state in a Key/Value store (e.g. { userid: xxx, end: false }. You can then check against the database store every time a picture is sent. An example of how your code would look like is:
bot.onText(/\/start/, msg => {
//saveToDb({chat_id: msg.chat.id, completed: false});
});
bot.onText(/\/end/, msg => {
//saveToDb({chat_id: msg.chat.id, completed: true});
});
bot.on("message", msg => {
// most of this code is just for logical purposes to explain the concept
if (typeof msg.image === "object") {
//const completed = checkDb(msg.chat.id);
if (completed !== true) {
// work with the image
}
}
});
Alternatively you can look into mau its aim is to solve this issue. It works well with node-telegram-bot-api, check the examples folder to get started on how it works.

Botbuilder - How to ignore user response without exiting prompt dialog

I have a multipatform bot (node.js through Azure Botframework) that uses a series of prompts to play a game with the user.
In group mode, such as on Kik or Slack, it waits for responses addressed to the bot.
However, I haven't found a way to simply ignore a message that doesn't address the bot. The solution I found ages ago was to simply reply with a new blank prompt:
builder.Prompts.text(session, "");
And this worked fine. However recently Slack must have changed something, because now this causes an error and the bot restarts.
How do I make the bot ignore certain responses without ending the dialog?
If suggesting a duplicate, please ensure it actually addresses this issue. Many other questions allow for the dialog to end, however this would interrupt the game.
You can setup middleware, as mentioned by Gary, that intercepts incoming messages and only processes it if the bot is #mentioned:
bot.use({
botbuilder: function (session, next) {
var message = session.message;
var botMri = message.address.bot.id.toLowerCase();
var botAtMentions = message.entities && message.entities.filter(
(entity) => (entity.type === "mention") && (entity.mentioned.id.toLowerCase() === botMri));
if (botAtMentions && botAtMentions.length) {
next();
}
},
send: function (event, next) {
next();
}
})

Chatbot messages do not show up in Facebook Messenger chat heads

I am developing a chatbot for Facebook Messenger using Microsoft Bot Framework. The bot sends the user proactive messages (reminders). Unfortunately, for some reason the messages never show up in a chat head (the Android widget for conversations), nor pop up a chat head if it wasn't present on the screen before. It does happen for other chatbots (Jarvis, for example).
This is the code that sends the reminders:
Reminder.find({ next_reminder: { $lte: new Date() } }, (err, res) => {
if (err !== null) {
return console.error(err);
}
res.forEach(reminder => {
// Build a notification message and address it to user who created the reminder
const msg = new builder.Message().text('...');
bot.beginDialog(reminder.user_address, '*:/sendReminder', {message: msg, nudnik: nudnik});
});
});
};
};
I have also tried bot.send(msg, () => ....) and session.beginDialog('sendReminder', msg). However, there is still no indication from Messenger when the message is received. What could go wrong here?
OK, I figured it out! Apparently, the default notification setting for a Facebook message is not to show a notification. To change it, in NodeJS you should add channel-specific data to the message with the following code:
msg = msg.sourceEvent({
facebook:
{notification_type: 'REGULAR'}
});
You can discover more in official documentation by Microsoft (here and here) and also in this Github discussion.

Resources