Why slack slash command returns "http_client_error" - node.js

I'm trying to build a very simple Slackbot using the Bolt Framework. I'm using ngrok to run this locally and when I invoke a slash command, ngrok just shows:
According to the Bot documentation, the app uses app.command() to handle slash commands. This is part of my code:
const {App, LogLevel} = require("#slack/bolt");
const app = new App({
token: "XXXX",
signingSecret: "XXXX",
logLevel: LogLevel.DEBUG
});
// The echo command simply echoes on command
app.command("/standup", async ({command, ack, say}) => {
// Acknowledge command request
ack();
say(`${command.text}`);
console.log("Entered into the app.command for /standUp");
});
Within Slack, the slash command is configured like this:
The bot works when interacting with messages, but just does receive and respond to Slash commands. I'm really new to this so any info would be great or just a push in the right direction.

I was able to figure out what the issue was. When I was trying above, I had the request url end with ../command, but it needed to stay the same as the configuration for Event Subscriptions with ../slack/events/.
I started to receive the commands after I made this change. As far as I can tell, this was not documented very well on Slack's docs, but I figured out the issue by seeing the configuration here and lots of trial and error. :)

Related

How to receive Discord.js interactions though POST requests at my endpoint

I am creating a Discord Bot using Discord.js and want to change it to receive interactions through POST requests instead of websockets, as the new option for Discord Apps:
You can optionally configure an interactions endpoint to receive interactions via HTTP POSTs rather than over Gateway with a bot user.
Slash commands and interactions works as expected with websocks by using:
client.ws.on('INTERACTION_CREATE', async (interaction) => {
// receive and answer the interaction
})
The problem is, I can't find on the documentation how to explicitly receive interactions through http POST neither options to set the listening PORT.

how does users.watch (in gmail google api) listen for notifications?

I am confused as to how should the watch feature in the gmail API be implemented to recieve the push notificatons inside a node.js script. Should I call the method inside an infinite loop or something so that it doesn't stop listening for notifications for email once after the call is made?
Here's the sample code that I've written in node.js:
const getEmailNotification = () => {
return new Promise(async (resolve, reject) => {
try{
let auth = await authenticate();
const gmail = google.gmail({version: 'v1', auth});
await gmail.users.stop({
userId: '<email id>'
});
let watchResponse = await gmail.users.watch({
userId: '<email id>',
labelIds: ['INBOX'],
topicName: 'projects/<projectName>/topics/<topicName>'
})
return resolve(watchResponse);
} catch(err){
return reject(`Some error occurred`);
}
})
Thank you!
Summary
To receive push notifications through PUB/SUB you need to create a web-hook to receive them. What does this mean? You need a WEB application or any kind of service that exposes a URL where notifications can be received.
As stated in the Push subscription documentation:
The Pub/Sub server sends each message as an HTTPS request to the subscriber application at a pre-configured endpoint.
The endpoint acknowledges the message by returning an HTTP success status code. A non-success response indicates that the message should be resent.
Setup a channel for watch the notifications could be summarized in the following steps (the documentation you refer to indicates them):
Select/Create a project within the Google Cloud Console.
Create a new PUB/SUB topic
Create a subscription (PUSH) for that topic.
Add the necessary permissions, in this case add gmail-api-push#system.gserviceaccount.com as Pub/Sub Publisher.
Indicate what types of mail you want it to listen for via Users.watch() method (which is what you are doing in your script).
Example
I give you an example using Apps Script (it is an easy way to visualize it, but this could be achieved from any kind of WEB application, as you are using Node.js I suppose that you are familiarized with Express.js or related frameworks).
First I created a new Google Apps Script project, this will be my web-hook. Basically I want it to make a log of all HTTP/POST requests inside a Google Doc that I have previously created. For it I use the doPost() equal to app.post() in Express. If you want to know more about how Apps Script works, you can visit this link), but this is not the main topic.
Code.gs
const doPost = (e) => {
const doc = DocumentApp.openById(<DOC_ID>)
doc.getBody().appendParagraph(JSON.stringify(e, null, 2))
}
Later I made a new implementation as a Web App where I say that it is accessible by anyone, I write down the URL for later. This will be similar to deploying your Node.js application to the internet.
I select a project in the Cloud Console, as indicated in the Prerequisites of Cloud Pub/Sub.
Inside this project, I create a new topic that I call GmailAPIPush. After, click in Add Main (in the right bar of the Topics section ) and add gmail-api-push#system.gserviceaccount.com with the Pub/Sub Publisher role. This is a requirement that grants Gmail privileges to publish notification.
In the same project, I create a Subscription. I tell it to be of the Push type and add the URL of the Web App that I have previously created.
This is the most critical part and makes the difference of how you want your application to work. If you want to know which type of subscription best suits your needs (PUSH or PULL), you have a detailed documentation that will help you choose between these two types.
Finally we are left with the simplest part, configuring the Gmail account to send updates on the mailbox. I am going to do this from Apps Script, but it is exactly the same as with Node.
const watchUserGmail = () => {
const request = {
'labelIds': ['INBOX'],
'topicName': 'projects/my_project_name/topics/GmailAPIPush'
}
Gmail.Users.watch(request, 'me')
}
Once the function is executed, I send a test message, and voila, the notification appears in my document.
Returning to the case that you expose, I am going to try to explain it with a metaphor. Imagine you have a mailbox, and you are waiting for a very important letter. As you are nervous, you go every 5 minutes to check if the letter has arrived (similar to what you propose with setInterval), that makes that most of the times that you go to check your mailbox, there is nothing new. However, you train your dog to bark (push notification) every time the mailman comes, so you only go to check your mailbox when you know you have new letters.

Connecting Heroku Webhooks with Discord

I am trying to have updates to my heroku app sent to a Discord channel via webhook. However, the delivery attempts fail. I've double checked the Payload URL and it is correct. Not sure how to proceed from here.
Heroku's webhook format is not compatible with Discord so you can't just put a Discord webhook URL into Heroku. You need a middle-man server to receive events from Heroku, and construct and send corresponding messages to Discord.
Found this JS code, should work (change params variable and where it says webhook to your webhook url)
let x = new XMLHttpRequest();
x.open("POST", `<webhook link>`);
x.setRequestHeader('Content-type', 'application/json');
let params = {
username: "Webhook Bot",
content: "<message content as a string>"
}
x.send(JSON.stringify(params));
i should mention that to mention a channel instead of #channel-name you'll have to use <#channelid>, for example <#1234567890> instead of #foo-bar
(this is my first post, sorry if it's a bit bad)
Without being able to see your code and the request structure you are using it will be hard to determine where the issue is coming from exactly, but one thing you might what to check is how you are sending the JSON payload to the Discord webhook URL.
Discord does not seem to accept the request unless you specify that the body of the payload is JSON. I discovered this because of an application I am working on currently. I know this answer is coming significantly after the fact, but it might help someone else down the line!

Implementing isRequestFromAssistant in Node.js on actions-on-google project fulfillment

I am having trouble implementing the isRequestFromAssistant method to verify requests to my fulfillment webhook. Using Node.js, I instantiate the following variables at the start of my index.js file:
const App = require('actions-on-google').ApiAiApp;
const app = new App({ request, response });
I then use "app" with the .ask and .tell and other methods throughout my functions.
The code I see in the docs for implementing isRequestFromAssistant is:
const app = new ActionsSdkApp({request, response});
app.isRequestFromAssistant('my-project-id')
.then(() => {
app.ask('Hey there, thanks for stopping by!');
})
.catch(err => {
response.status(400).send();
});
If I leave out the first line and use my existing app variable, created with the .ApiAi method instead of the .ActionsSdkApp method, it doesn't work. If I create a new variable App1 and app1 using the .ActionsSdkApp method and change the above code to be app1.isRequestFromAssistant, it also doesn't work. I have tried other variations with no luck.
When I say it doesn't work, I mean I receive a 500 Internal Server Error when I call it. I am hosting it with NGROK currently. I am still a beginner with Node.js, although I have managed to get the other 700 lines of code working just fine, learning mostly from Google searches and reading these forums.
You have a few things going on here which, individually or separately, may be causing the problem.
First - make sure you have the most recent version of the actions-on-google library. The isRequestFromAssistant() function was added in version 1.6.0, I believe.
Second - Make sure you're creating the right kind of App instance. If you're using Dialogflow (formerly API.AI), you should be creating it with something like
const App = require('actions-on-google').DialogflowApp;
const app = new App( {request, response} );
or
const { DialogflowApp } = require('actions-on-google');
const app = new DialogflowApp( {request, response} );
(They both do the same thing, but you'll see both forms in documentation.) You should switch to DialogflowApp from ApiAiApp (which your example uses) to reflect the new name, but the old form has been retained.
If you're using the Actions SDK directly (not using Dialogflow / API.AI), then you should be using the ActionsSdkApp object, something like
const { ActionsSdkApp } = require('actions-on-google');
const app = new ActionsSdkApp({request: request, response: response});
(Again, you'll see variants on this, but they're all fundamentally the same.)
Third - Make sure you're using the right function that matches the object you're using. The isRequestFromAssistant() function is only if you are using the Actions SDK.
If you are using Dialogflow, the corresponding function is isRequestFromDialogflow(). The parameters are different, however, since it requires you to set confirmation information as part of your Dialogflow configuration.
Finally - If you're getting a 500 error, then check your logs (or the output from stderr) for the node.js server that is running. Typically there will be an error message there that points you in the right direction. If not - posting that error message as part of your StackOverflow question is always helpful.
Set the secure (randomly generated) auth header & key values in the dialogflow Fulfillment page, then in nodejs:
if (app.isRequestFromDialogflow("replace_with_key", "replace_with_value")) {
console.log("Request came from dialogflow!");
// rest of bot
} else {
console.log("Request did not come from dialogflow!");
response.status(400).send();
}
Also see: https://developers.google.com/actions/reference/nodejs/DialogflowApp#isRequestFromDialogflow

Firebase Server NodeJS failing to connect with Service Account

I have a pretty simple NodeJS server that I'm using to monitor our Firebase Database. My code is basically identical to the sample on the Firebase documentation:
var firebase = require("firebase");
firebase.initializeApp({
databaseURL: 'https://myurl.firebaseio.com/',
serviceAccount: 'path/to/json.json'
})
Now the issue I'm having is when I run this code from within our network, it doens't seem to be connection as a have a block of code right after to read some data and it never gets ran:
var nodeRef = this.db.ref("node");
nodeRef.on("child_added", function (snapshot, prevChildKey) {
// ...
}, function (error) {
console.log(error);
})
If I give everyone write access to the database, I can take out the serviceAccount setting on the initializeApp call, and everything works perfectly. I've tried running Fiddler to see what it might be making a request to that is failing, but I'm not seeing any requests pop up in Fiddler at all. Any ideas what this might be calling that our proxy would need to allow?
Our IT team found what the problem was, I had asked them to open accounts.google.com in our proxy server. It got set to "allow" instead of "tunnel".
According to them, the HSTS headers were causing the SSL decryption on the proxy unless it was set to tunnel, which was causing the "self signed certificate" error I mentioned above in the comments.
For me, disabling Kaspersky got it to work. You can try that.

Resources