How to answer back with images in wit.ai? - facebook-messenger

I am trying to create a fb_messenger bot using wit.ai.In wit.ai,i can only do answering and question which is only text.But I want to answering back to user by showing images.How to do it?Please guide me.
Thank you very much.

You need to send the image in your Wit action using the messenger Bot:
Example if you're using Node js:
const actions = {
/**
* This is used by the "Bot sends" action in Wit
* #param sessionId
* #param text
* #returns {Promise.<T>}
*/
send({sessionId}, {text}) {
// Our bot has something to say!
// Let's retrieve the Facebook user whose session belongs to
const recipientId = sessions[sessionId].fbid;
if (recipientId) {
// Yay, we found our recipient!
// Let's forward our bot response to her.
// We return a promise to let our bot know when we're done sending
//bot is a simple wrapper for Messenger node code provided [here][1]
return bot.sendTextMessage(recipientId, text)
.catch((err) => {
console.error(
'Oops! An error occurred while forwarding the response to',
recipientId,
':',
err.stack || err
);
});
} else {
console.error('Oops! Couldn\'t find user for session:', sessionId);
// Giving the wheel back to our bot
return Promise.resolve()
}
},
['my-custom-action']({sessionId, context, entities, message}) {
//Api calls ...
//now i got an image URL i want to send to the user
return bot.sendImageMessage(recipientId, image_url);
return Promise.resolve(context)
},
Don't forget to delete the "Bot sends" part from your story on Wit.ai, this is so you don't send both the Image and the URL.
Hope this helps!

You need to use the image attachment template.
curl -X POST -H "Content-Type: application/json" -d '{
"recipient":{
"id":"<USER_ID>"
},
"message":{
"attachment":{
"type":"image",
"payload":{
"url":"<IMAGE_URL>"
}
}
}
}' "https://graph.facebook.com/v2.6/me/messages?access_token=<PAGE_ACCESS_TOKEN>"
More information here:

Related

Discord.js slash commands type 5

So I have been developing a bot recently and I have implemented the slash commands into said bot. I have come across the need for a type 5 command "response" but I can't seem to find good documentation on the slash commands. I can't seem to make it "stop thinking". Any help would be appreciated!
EDIT: I found that you need to edit the interaction response (https://discord.com/developers/docs/interactions/slash-commands#interaction-response) but I'm not using webhooks I'm using a bot and I don't want to have to get another npm library if I don't have to. So how do I edit my interaction?
I have solved this, if you want to know how I did here is some code.
if your interaction responder looks like this:
if (interaction.data.name === 'whatever') {
whatever.whatever (interaction)//i am using a command handler to put
//the actual event into a different file
}
and your "interaction message sender" looks like this: (notice it's type 5)
module.exports.whatever = (interaction) => {
client.api.interactions(interaction.id, interaction.token).callback.post({
data: {
type: 5
}
})
};
then it will say "{botname} is thinking" with a little ellipses, and after 15 minutes if nothing happens it will fail the interaction. If you want to make it "stop thinking" you have to edit the message. I am using the axios npm library (https://www.npmjs.com/package/axios) and if you just put in this code it should edit your interaction message. this goes at the top of your file with your requirements:
const axios = require('axios')
const appId = ''//bot id goes here
and somewhere near the bottom of your file maybe put in this:
const editInteraction = async (client, interaction, response) => {
const data = typeof response === 'object' ? { embeds: [ response ] } : { content: response };
const channel = await client.channels.resolve(interaction.channel_id);
return axios
.patch(`https://discord.com/api/v8/webhooks/${appId}/${interaction.token}/messages/#original`, data)
.then((answer) => {
return channel.messages.fetch(answer.data.id)
})
};
then you will have the basic code structure to edit the message, now you just need to edit the message. to do that, in your code, do this:
if (interaction.data.name === 'whatever') {
whatever.whatever (interaction).then(m => {
editInteraction(client, interaction, '>:(')//this will actually edit the message so
//instead of " >:( " put in what you want to edit you message to be
})
}
then you can run that command and it will say the bot is thinking then after whatever event you want to run it will edit it to say whatever!

How to send a message based on event Google PubSub?

I need some help with PubSub...
I need to send a message to a topic every time someone accept cookies in my website. This message should contain the encodedURL that contains the services accepted.
I have this script:
const topicName = "myTopic";
const data = JSON.stringify({
encodeConsentURL:""
});
// Imports the Google Cloud client library
const { PubSub } = require("#google-cloud/pubsub");
// Creates a client; cache this for further use
const pubSubClient = new PubSub();
async function publishMessageWithCustomAttributes() {
// Publishes the message as a string, e.g. "Hello, world!" or JSON.stringify(someObject)
const dataBuffer = Buffer.from(data);
// Add two custom attributes, origin and username, to the message
const customAttributes = {};
const messageId = await pubSubClient
.topic(topicName)
.publish(dataBuffer, customAttributes);
console.log(`Message ${messageId} published.`);
console.log(customAttributes);
}
publishMessageWithCustomAttributes().catch(console.error);
This code works, it sends the message, what I'm finding very hard to do is how to set everything right for running this code in my cookie script. In my cookie script I have a function that writes the cookie, in the same function I would like to send the message, is this possible? Thanks in advance!
It is a bit late, but I don't get it, if you already have a working cookie script and a working publish script, isn't it just about putting them together?
If you still need help I'll be happy to help you
Something like
const runEverything = async () => {
try {
await checkCookiesThing()
await publishMessage()
} catch (e) {
console.error(e)
}
}

How to post a message in an existing DM as a Slack Bot

My understanding of the chat.postMessage method of the Slack Web API is that you can, as a bot with a bot token, post messaged to public channels. However, if you want to post to DMs - you would need to request a user token and then post on behalf of the user
However, I've used a few apps that are able to post into DMs as an app (and therefore, I assume, are using a bot token). To me this is ideal, so you're not bugging every person in the Slack workspace to get their user token
Can anyone tell me how this is done?
For reference, here is the code I use to post a message as a bot. It does not work for DMs or for private channels the bot has not been invited to. Would love to fix that. Thanks
function getQueryString(data = {}) {
return Object.entries(data)
.map(([key, value]) => `${encodeURIComponent(key)}=${encodeURIComponent(value)}`)
.join('&');
}
function postMessageInSlack(bot_token, channelID, userID, message, send_blocks, endpoint) {
const options = {
headers: {'Content-Type': 'application/x-www-form-urlencoded'}
};
const data = {
token: bot_token,
channel: channelID,
text: `${message} from <#${userID}>`,
blocks: JSON.stringify(send_blocks),
}
delete axios.defaults.headers.common["Content-Type"];
axios.post(endpoint,
data, {
options,
transformRequest: getQueryString}
)
.then(res => console.log("result is ", res))
.catch(err => console.log("the error is ", err))
}
You need to open a new conversation with the user, that's if there was none open. To so this you need the conversations.open method. This will return a response that contains the conversation id. You can now use the conversation id in place of the channel id in your chat.postMessage method.

Error when sending POST request from React app to Rocket backend returns failure

I'm writing a simple web with Rocket as backend and React as frontend.
The code snippet looks like this for login page
#[post("/login", data = "<data>")]
pub fn login(
conn: DbConn,
mut cookies: Cookies<'_>,
data: Form<LoginForm>,
) -> Result<JsonValue, NotFound<String>> {
let valid_account = match Account::find_by_email(&*conn, data.email.as_str()) {
Ok(account) => {
if account.password == data.password {
account
} else {
return Err(NotFound("Incorrect email or password!".to_string()));
}
}
Err(_) => return Err(NotFound("Incorrect email or password!".to_string())),
};
cookies.add_private(
Cookie::build(AUTH_COOKIE, valid_account.id.to_string())
.same_site(rocket::http::SameSite::Strict)
.finish(),
);
Ok(json!({
"email": valid_account.email,
"name": valid_account.name,
}))
}
Code for main.rs
fn main() {
rocket::ignite()
.mount("/", routes![
account::login::login,
],
)
.register(catchers![errors::unauthorized])
.attach(rocket_cors::CorsOptions::default().to_cors().unwrap())
.manage(establish_connection())
.launch();
}
and code for React when trying to send the post request
export const postForm = async (
pathUrl: string,
postInfo: { [name: string]: any }
) => {
let axiosConfig = {
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
'Access-Control-Allow-Origin': '*',
},
};
try {
const response = await axios.post(
baseUrl + pathUrl,
querystringify.stringify(postInfo),
axiosConfig
);
return response.data as CurrentUser;
} catch (err) {
console.log(err);
return Promise.reject(err.response);
}
};
The code works fine it I enter the correct email and password.
However, it cannot capture the error message if I enter the wrong credentials.
Rocket log are the same between successful login and failure login which are
OPTIONS /login:
=> Error: No matching routes for OPTIONS /login.
=> Warning: Responding with 404 Not Found catcher.
=> CORS Fairing: Turned missing route OPTIONS /login into an OPTIONS pre-flight request
=> Response succeeded.
POST /login application/x-www-form-urlencoded:
=> Matched: POST /login (login)
=> Outcome: Success
=> Response succeeded.
and the error log in browser I captured was Error: "Request failed with status code 404" which was not the expected error message hard coded inside post function.
I believe it has something to do with Option or preflight processed inside Rocket which maybe in the purpose of security. But how can I suppress the system error and let my code to take over?
I have read previous SO post like state undefined: while sending post request from react app and GitHub issues like https://github.com/SergioBenitez/Rocket/issues/25. And still cannot find answer for my problem.
Thanks in advance!
Apparently I made several mistakes here due to unfamiliar with Rocket and React.
List here in case someone made the similar mistakes.
The 404 status code is from the first code snippets Result<JsonValue, NotFound<String>>. So if we write the return type as Result<JsonValue, Unauthorized<String>>, it would return 401 as unauthorized user.
Second, axios only receives json type and cannot parse string (correct me if I'm wrong). So we need to change the return type in server to Result<JsonValue, Unauthorized<JsonValue>>.

Twilio & NodeJS: can't find and delete Media instances/resources

I'm using Twilio's NodeJS module & API to send out MMS messages with images attached (from a remote URL), and I want to delete the Media instances that get created on Twilio servers as soon as I send out the messages.
My messages send out correctly, and in the callback, I'm trying to 1) list media instances for the current message, then 2) loop through those instances and delete. The problem is that the mediaList array that comes back from the API for a current message is always empty.
Here's my code:
twilio_client.messages.create({
body: "Thanks for taking a photo. Here it is!",
to: req.query.From,
from: TWILIO_SHORTCODE,
mediaUrl: photo_URL,
statusCallback: STATUS_CALLBACK_URL
}, function(error, message) {
if (!error) {
twilio_client.messages(message.sid).media.list(function(err, data) {
console.log(data);
// The correct object comes back as 'data' here per the API
// but the mediaList array is empty
}
console.log('Message sent via Twilio.');
res.status(200).send('');
} else {
console.log('Could not send message via Twilio: ');
console.log(error);
res.status(500).send('');
}
});
So, it turns out that trying to get the media list at the point I was trying to doesn't work because the media instances didn't exist yet.
I have a separate little app running at the statusCallback (I supply a URL via a constant in the code above, STATUS_CALLBACK_URL), that until now, just checked to see if a message I tried to MMS to a user wasn't handled properly by Twilio, and alerted the user to a problem via SMS. So, I added a check in that same app to see if the message was actually 'sent' to the user, and then checked for and deleted the media instance(s) associated with the message at that point, and it works fine. Here's my code:
// issue message to user if there's a problem with Twilio getting the photo
if (req.body.SmsStatus === 'undelivered' || req.body.SmsStatus === 'failed') {
twilio_client.messages.create({
body: "We're sorry, but we couldn't process your photo. Please try again.",
to: req.body.To,
from: TWILIO_SHORTCODE
}, function(error, message) {
if (!error) {
console.log('Processing error message sent via Twilio.');
res.send(200,'');
} else {
console.log('Could not send processing error message via Twilio: ' + error);
res.send(500);
}
});
}
// delete media instance from Twilio servers
if (req.body.SmsStatus === 'sent') {
twilio_client.messages(req.body.MessageSid).media.list(function(err, data) {
if (data.media_list.length > 0) {
data.media_list.forEach(function(mediaElement) {
twilio_client.media(mediaElement.sid).delete;
console.log("Twilio media instance deleted");
});
}
});
}

Resources