My app uses Slack to send users messages. In those Slack messages, buttons are used as links to my app. But in doing so, I encountered the known warning icon issue. So I created a route in my back-end just to send a 200 response to Slack. But for some reason, the warning icon is still there, which means Slack doesn't receive my acknowledgement response... And I don't know why.
Here's my route, trying both a classic 200 response and the solution mentioned in the Github issue (see link above) :
router.post(
"/mySlackRoute",
asyncHandler((req, res) => {
const slackApp = req.context.slackApp;
slackApp.app.action("mySlackButtons", ({ ack }) => ack());
res.sendStatus(200);
})
);
And here's how my Slack message button is created :
{
type: "button",
text: {
type: "plain_text",
emoji: true,
text: text,
},
url: baseUrl + "/api/slack/mySlackRoute",
action_id: "mySlackButtons",
};
Related
I have a node.js app that I have created a discord bot to interact with. I would like it so that if a particular event happens with my node.js app that it will send a message to a particular channel in my discord server.
This is my first time using discord.js. However, my thought was to create a function that I can call to send my messages. However, it would seem that I need to wait for my client to be ready first.
Alternatively, would I just have to instantiate a new client every time I want to send a message and wait for it to come available before I send the message I want?
I feel like there has to be a better way... Is there a clean way that I can set up this basic discord bot that I can just call a function to send a message from anywhere within my app?
Here is the code that I have now:
import { Client, Events, GatewayIntentBits } from "discord.js";
import { botToken, CHANNEL_ID } from "../../config.js";
const client = new Client({ intents: [GatewayIntentBits.Guilds] }); // Create a new client instance
// When the client is ready, run this code (only once)
// We use 'c' for the event parameter to keep it separate from the already defined 'client'
client.once(Events.ClientReady, c => {
console.log(`Ready! Logged in as ${c.user.tag}`);
client.channels.cache.get(CHANNEL_ID).send("Hello!");
});
// Log in to Discord with your client's token
client.login(botToken);
"I would like it so that if a particular event happens with my node.js app that it will send a message to a particular channel in my discord server."
It sounds like you're looking for webhooks. Webhooks are a way for an external source, such as your Node.js app, to send messages to a Discord channel without having to log in as a bot. Instead of using a Discord bot, you can use a webhook to send messages to a channel as if they were posted by a bot.
Using a webhook is simple; you just need to make an HTTP POST request to a URL provided by Discord, with the message you want to send in the body of the request. Discord will then post that message to the specified channel.
This is useful in cases where you want to receive notifications from your app in a Discord channel, or simply want to send messages to a channel without having to log in as a bot. It's a clean and efficient way to integrate your app with Discord.
Here is an example of a sendMessage function. It takes two arguments, payload and webhookUrl. If the payload is not a string, it is assumed to be an object that conforms to the Discord webhook format and will be used as is.
function sendMessage(payload, webhookUrl) {
const data = typeof payload === 'string' ? { content: payload } : payload;
return new Promise((resolve, reject) => {
fetch(webhookUrl, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(data),
})
.then((response) => {
if (!response.ok) {
reject(new Error(`Could not send message: ${response.status}`));
}
resolve();
})
.catch((error) => {
console.error(error);
reject(error);
});
});
}
If you're using node.js v18+, you can use the built-in fetch, if not, you'll need to install a library like node-fetch, axios, or something else.
Here is an example how you could use it:
// send a simple message
sendMessage('Hello from my app!', WEBHOOK_URL).catch((error) =>
console.error(error),
);
// send a message, but change the username and the avatar
sendMessage(
{
content: 'Hello from my app!',
avatar_url: 'https://i.imgur.com/KEungv8.png',
username: 'Test Hook',
},
WEBHOOK_URL,
).catch((error) => console.error(error));
// send an embed and change the user again
sendMessage(
{
avatar_url: 'https://i.imgur.com/ofPowdD.png',
username: 'Cattian Hook',
embeds: [
{
title: 'Cats, cats, cats',
color: 0xe7d747,
thumbnail: {
url: 'https://i.imgur.com/2bvab7y.jpeg',
},
},
],
},
WEBHOOK_URL,
).catch((error) => console.error(error));
And here is the result:
If you're already using discord.js, you can use the WebhookClient:
import { WebhookClient } from 'discord.js';
const webhookClient = new WebhookClient({
url: WEBHOOK_URL,
});
webhookClient.send({
content: 'Discord.js webhook test',
username: 'DJS Webhook',
avatarURL: 'https://i.imgur.com/KEungv8.png',
});
To create a webhook, you'll need to go to your discord server settings and click on APPS => Integrations. Then click on the Create Webhook button. There you can select the channel where you want the messages to be sent.
Once the webhook is created, you can click the Copy webhook URL button and use that URL.
I have a Telegram bot that processes payments. The payments work as they should, however, I have not been able to show receipt after a successful payment.
The current behavior is:
user clicks on PAY button, fills the card information and pays for the service
payment is processed and message about successful transaction is sent
at this point, I would like for the PAY button to change to RECEIPT button
The current behavior on screenshot:
Desired behavior:
The desired behavior was screenshoted from chat with #ShopBot, which is mentioned in Telegram docs as a test tool.
The only mention about how the "receipt" is handled I could find in the Telegram docs were these two sentences at https://core.telegram.org/bots/payments :
If the invoice message was sent in the chat with #merchantbot, it becomes a Receipt in the UI for the user — they can open this receipt at any time and see all the details of the transaction.
If the message was sent to any other chat, the Pay button remains and can be used again. It is up to the merchant bot whether to actually accept multiple payments.
However, I don't understand how to achieve this in the code. As far as I know, the invoice message WAS sent to the chat with my bot (as in the first sentence) so it SHOULD become a Receipt.
The bot is written in Node.js and uses webhook to handle messages. The code section of the webhook important for this question:
router.route('/')
.post(async (req, res) => {
try {
// if pre_checkout_query is defined, there was an attempt for payment
if (req.body.pre_checkout_query) {
// use answerPreCheckoutQuery Telegram method
...
}
const message = req.body.message || req.body.edited_message;
// this means user's payment was successful
if (message.successful_payment) {
// success, deliver goods or services
// send message about successful payment
...
}
} catch (err) {
...
}
})
The invoice is sent with sendInvoice method like this:
const url = `https://api.telegram.org/bot${process.env.TELEGRAM_BOT_TOKEN}/sendInvoice`;
const response = await axios.get(url, {
params: {
chat_id: chatID,
title: 'SOME TITLE',
description: 'some decription',
payload: 'SOME-PAYLOAD',
provider_token: process.env.STRIPE_API_TOKEN,
currency: 'EUR',
prices: JSON.stringify([
{
label: 'some label',
amount: 200,
},
]),
},
});
The two methods from the API that are used for processing the payments are sendInvoice and answerPreCheckoutQuery but neither of them contains any argument that would possibly change the output the way I want. Am I missing something?
Note at the end: despite all this, the payments works. This is just a cosmetic change I would like to achieve.
I also had this problem, specify a parameter: start_parameter='unique-string'
I have a use case where i would like to send a slack user a message of which i know the id of a notification once and a while using the bot framework.
Right now i have the following:
server.get("/api/notify", async (req, res) => {
await adapter.createConversation(conversationReference, async turnContext => {
await turnContext.sendActivity("proactive hello");
});
res.setHeader("Content-Type", "text/html");
res.writeHead(200);
res.write(
"<html><body><h1>Proactive messages have been sent.</h1></body></html>"
);
res.end();
});
where a conversation reference looks like:
const conversationReference = {
user: { id: "ID3:ID2", name: "user1" },
bot: { id: "ID1:ID2", name: "bot1" },
conversation: {
isGroup: false,
id: "ID1:ID2:ID3",
conversationType: "slack",
tenantId: "",
name: ""
},
channelId: "slack",
serviceUrl: "https://slack.botframework.com/"
};
But it only works if the user has talked to the bot since the bot has booted. But after a restart this won't work anymore until the user initiates a conversation.
When I try to send a pro active message after the bot rebooted and the user hasn't started a conversation after that i get the following exception:
UnhandledPromiseRejectionWarning: Error
at new RestError (/usr/app/node_modules/#azure/ms-rest-js/dist/msRest.node.js:1397:28)
at /usr/app/node_modules/#azure/ms-rest-js/dist/msRest.node.js:1849:37
at process._tickCallback (internal/process/next_tick.js:68:7)
My question is: How can i persist this state, so i can still send pro active messages after a reboot?
Aha! This part of your question is the key:
But it only works if the user has talked to the bot since the bot has booted. But after a restart this won't work anymore until the user initiates a conversation.
This is almost definitely a TrustServiceUrl Issue. Please see this answer for additional context.
Basically, on reboot, the bot forgets that it's okay to talk to that user. You need to "Trust" the ServiceUrl of the user/activity to ensure the bot knows it's okay to message them.
I have a built react front end, I used a simple boilerplate to connect the express with react. There seems to be SO many different ways to setup a SIMPLE RESTful api that I'm getting lost. I'm trying to do some very simple backend to front end communication.
I have express do a get request to push to the back and am using Axios to get the data:
AccountsDB is just basic JSON data for internal testing
[
{
"id": "5b68d6f13e2c773581221620",
"index": 0,
"firstName": "Josefa",
"lastName": "Lynch",
"pin" : 1234
}
]
Inside my express index.js I have a simple GET
app.get('/api/getAccounts', (req, res) => res.json(AccountsDB));
within my React I fetch the data with axois:
componentDidMount () {
axios.get ('/api/getAccounts')
.then (res => this.setState({ Accounts : res.data}));
}
Totally works. I display the account within the main react component.
Inside the component I also have a forum to "create" a a new account, and push it to the AccountsDB file just for internal testing (I'm learning backend, will connect mongoDB after).
My logic for POST method (found here Axios Cheet Sheet):
axios.post('/api/putAccounts', {
firstName: 'Fred',
lastName: 'Flintstone'
})
.then(function (response) {
console.log(response);
})
.catch(function (error) {
console.log(error);
});
Which I attach onto a button to post the data. I open up POST man and navigate to '/api/putAccounts' and see nothing.
I don't understand how to exactly gather the data into express. My silly attempt :
app.post('/api/putAccounts', (req,res) => {
// res.send("sent!") // post man see's this?
// var account = req.account;
// res.send(req.firstName);
});
To elaborate in more detail ...
React app is on -> localhost:3000
Express app is on -> localhost:8080
using webpack and a proxy:
devServer: {
port: 3000,
open: true,
proxy: {
'/api': 'http://localhost:8080'
}
under 'http://localhost:3000/admin' (in my react app) I have a button that has the axios.post that send the firstName : Fred and lastName : Flintstone to '/api/putAccounts'
I'm trying to have my express server catch the post so I can manipulate it and add it into a database.
Before I get into database stuff, I'm trying to make sure I understand how POST works (I understand GET). So I'm trying to get the data, and display it somewhere, this is what I mean by viewing it in postman.
Maybe I'm going about this all wrong, hence why the confusion.
In postman you need to send firstName and lastName in req body like below while making post request
{
"firstName": "Hi",
"lName": "Hello"
}
So that you can do req.body.firstName to get its value below
app.post('/api/putAccounts', (req,res) => {
const fName = req.body.firstName;
const lName = req.body.lastName;
res.json({"fName":fName, "lastName": lName});
});
I'm having trouble using the reminder method to set a reminder using the Slack API.
https://api.slack.com/methods/reminders.add
I want to set a reminder for various people in our workspace. My understanding of the Slack API docs is that a workspace token is needed for permission, which I have created. See https://api.slack.com/docs/token-types#workspace
In POSTing the reminder request, I always get the error { ok: false, error: 'user_not_specified' }. I have specified a user as part of the payload, as well as text, time and the bearer token.
Strange, because the docs say that user is optional. Removing the user from the payload results in the same error.
I'm getting the same error in both Postman and in a simple snippet using the Node Slack API library:
const { WebClient} = require('#slack/client');
const token = process.env.SLACK_TOKEN || require('./.config').SLACK_API_TOKEN;
const web = new WebClient(token);
web.reminders.add({text: 'clean up duty', time: 'in 1 minute', user: 'U0FKQ3N94'})
.then((res) => {
console.log(res);
})
.catch(console.error);
Any idea what I am doing wrong?