slack how to know if bot recently posted - node.js

I am using botkit, i have a bot that responses to a certain word.
But i don't want the bot to response if it recently did so.
Currently i am using channels.history method to retrieve 4 recent messages then find the bot id, if its there it won't reply. This is not pretty, i've been searching for useful methods to use but i can't find any. I just want to find out if the bot recently posted or not and do actions base on it.
const targetBotID = 'GKALXJCM6'
bot.api.channels.history({
channel: message.channel,
latest: message.ts,
count: 4,
inclusive: 1,
}, function(err, response) {
if(err) { bot.reply(message, 'Something is wrong with me, check log if there is??'); }
if(response){
const recentPostFound = response.messages.filter(function (member) {
return member.user === targetBotID;
});
if(recentPostFound){
return bot.reply();
}
return bot.reply(answer) // Answer if no matching id found
}
});

I can see two solutions to your issue:
Record previous actions of your bot in some kind of app context (e.g. database). Then you can verify each time if your bot already answered.
Consider using Events API instead of loading the chat history each time. Then your bot gets exactly one event request for each new message in a channel and you can be sure that your bot will only react once.

Related

How to get a thread reply's content from reaction_added event?

I'm building a slack FAQ app that uses message reactions to gather the best answers to questions. My plan is to save any Slack messages with positive reactions by using the reaction_added event to get the TS attribute and then the conversations.history method to get the message's content.
This works well for parent-level or non-threaded messages, however it doesn't work for reply messages inside threads. For some reason the conversations.history method returns an unrelated message when using the TS of a thread reply.
I've checked the Slack API conversations.history method documentation to see if replies are handled in any special way. I reviewed conversations.replies method to see if it might be helpful, but since reaction_added event simply provides a TS id for the message and no thread_ts value that can be used with the conversations.replies method.
I'm using bolt framework. Here's a snippet of the code that tries to use the reaction_added event with conversations.history method to get the message content:
app.event('reaction_added', async ({ event, context, say }) => {
try {
const result = await app.client.conversations.history({
token: process.env.SLACK_USER_TOKEN,
channel: event.item.channel,
latest: event.item.ts,
limit: 1,
inclusive: true
});
save(`${result.messages[0].text}`);
}
catch (error) {
console.error(error);
}
});
Expected result:
Message contents of thread reply that a reaction is posted for
Actual result:
Message contents of the latest message in the slack channel
I'm not sure if it changed recently or I misread the documentation, but conversations.replies API endpoint does not require a thread_ts value containing the parent thread timestamp in order to retrieve a thread reply.
The event.item.ts value provided by the reaction_added event is sufficient to retrieve the message contents of the reply where a reaction was added.
So to get the message contents of a message where a reaction was added, you can update the code in my original question to:
app.event('reaction_added', async ({ event, context, say }) => {
try {
const result = await app.client.conversations.replies({
token: process.env.SLACK_USER_TOKEN,
channel: event.item.channel,
ts: event.item.ts
});
save(`${result.messages[0].text}`);
}
catch (error) {
console.error(error);
}
});

When bot is restarted or turned on, do a specific function

I'm trying to make it so that when my bot gets a restart, in the ready.js file it will search for webhooks it made in all of the guilds the bot is in, the bot will then use that webhook and send messages through it. I wasn't able to get anywhere and this is in JS.
I've referred to the documentation for Discord.JS and really haven't gotten anywhere. I tried to get the client ID from webhook.owner and see if the bot's ID matches up with it. I am not sure how to extract the client ID from webhook.owner
guild.fetchWebhooks()
if(webhook.owner == `${bot.user.id}`);
(suggested)
guild.fetchWebhooks()
if(webhook.owner == `${bot.user.username}`);
(actual)
This is the only code I could come up with, can add full file if needed.
I expect a bot that when it restarts (bot.on) then it will search through all of the guilds it is in and find webhooks that it owns, and send messages through it without doing it to another active webhook.
What ends up happening is that my bot just sends out a mention of the bot.
Do something like this:
bot.on('ready', async () => { // on ready
await bot.guilds.forEach(async guild => { // in all guilds:
const webhooks = await guild.fetchWebhooks(); // check for Webhooks
await webhooks.forEach(async webhook => { // for all found Webhooks:
if (webhook.owner.id == bot.user.id) { // check if bot owns them
webhook.send('test'); // Do something with the Webhook example
}
});
});
});

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.

get_started button sends messaging_postbacks callbacks thrice

Hi I am using nodejs and developing a bot on facebook messenger platform. I have my webhook subscribed only to messages and messaging_postbacks events. However, when I test the bot, it seems to send callback three times. This is my webhook code
server.post('/', (req, res, next) => {
let postback = req.body.entry[0].messaging[0].postback;
if (postback.payload === 'Greet User'){
console.log(postback);
}
}
When I test my bot, the postback object gets printed thrice as below.
{ payload: 'Greet User', title: 'Get Started' }
{ payload: 'Greet User', title: 'Get Started' }
{ payload: 'Greet User', title: 'Get Started' }
Any help how to avoid it? I read in some of the posts here that I should deselect message_reads and message_deliveries subscriptions. But I do not have those selected anyways. Not sure what else I am missing? Please help me.
I have found the problem after some more searching on the net and debugging it myself. In case, if others reading this might be interested to know, the issue was I was not sending back 200 status back to facebook. I found the hint regarding the need to do that in this stack overflow post.
Facebook webhook making multiple calls for the same message?
After sending the 200 response, I m not getting this issue. So relieved :)

builder.Prompts.text not working after being hosted remotely

I have a simple bot that fetches news articles based on a user prompt. The entire flow works fine locally using emulator but after being deployed to a server the bot fails when it hits a builder.Prompts.text block. Below is my code and you will see a "Asking article count" prompt which is where it stops in flow.
Bot shows accepted when testing on the BOT Framework page
Bot is receiving messages via WebChat and Slack
Bot also shows 0 issues for each channel after interacting
var bot = new builder.UniversalBot(connector);
var intents = new builder.IntentDialog();
bot.dialog('/', intents);
var HHCC = require('./hhcc.js');
intents.matches(/^news/i, [
function(session) {
console.log("Intent Given!");
session.beginDialog('/news');
},
function(session, results) {
session.send('Enjoy reading!');
}
]);
bot.dialog('/news', [
function(session) {
console.log("Asking article count");
builder.Prompts.text(session, 'How many articles would you like to see?');
},
function(session, results) {
session.sendTyping();
session.conversationData.count = results.response;
HHCC.getNews(session.conversationData.count, session, function(newsArticles) {
newsArticles.forEach(function(newsCard) {
session.send(newsCard);
});
session.conversationData.news = newsArticles;
console.log(newsArticles);
session.endDialog();
});
}
]);
server.post('/api/messages', connector.listen());
Ive checked all logs and can't seem to find any clues as its failing pretty silently.
Have you attempted using builder.Prompts.number() instead of .text()? It only accepts numbers and (I'm guessing you're doing this) you won't have to parse the results.response into a number. Without provided error messages or logs it's difficult to help.
One thing you might have to look out for (if using builder.Prompts.number) is if a user provides a decimal, as the prompt will accept this input, requiring the bot to round to the nearest integer.
Also, if you've saved the results.response into your session object, you will not need to pass in session.conversationData.count as another parameter to HHCC.getNews(). You can instead access it from session in your function.

Resources