How can I receive an attachment in form of an image through the Facebook Messenger API?
Their documentation only provides instructions on how to receive text-based messages.
I am not sure what language you are using to code your bot but since you are referring to the facebook documents where most of the messenger code snippets are in node.js
Here's something for you to try, let me know if this helps.
app.post('/webhook/', function (req, res) {
//Getting the mesagess
var messaging_events = req.body.entry[0].messaging;
//Looping through all the messaging events
for (var i = 0; i < messaging_events.length; i++) {
var event = req.body.entry[0].messaging[i];
//Checking for attachments
if (event.message.attachments) {
//Checking if there are any image attachments
if(atts[0].type === "image"){
var imageURL = atts[0].payload.url;
console.log(imageURL);
}
}
}
}
In February 2017 I came across the same issue and struggled to get this up and running for a very long time. Turns out that the message.attachments comes in as object, where the actual attachment is within the object.
The structure goes like this:
Attachments Object > JSON Response >Type & Payload > URL
app.post('/webhook/', function(req, res) {
let messaging_events = req.body.entry[0].messaging
for (let i = 0; i < messaging_events.length; i++) {
let event = req.body.entry[0].messaging[i]
let sender = event.sender.id
// Check if it's a message
if (event.message) {
//Create the attachment
let attachment = event.message.attachments
// Here we access the JSON as object
let object1 = attachment[0];
//Here we access the payload property
let payload = object1.payload;
// Finally we access the URL
let url = payload.url;
console.log(url)
}
else if (event.message && event.message.text) {
// Here you can handle the text
console.log("Just Text")
}
}
res.sendStatus(200)
})
The more compact version without explanations looks like this:
if (event.message) {
let attachment = event.message.attachments
console.log(attachment[0].payload.url)
}
As added bonus, you could also check if the type is an Image. You can achieve that by adding doing this adjustment:
if (event.message && ) {
let attachment = event.message.attachments[0]
if (attachment.type === "image") {
console.log(attachment.payload.url)
}
}
Hope this helps,
Julian
While in PYTHON to receive and save an image attachment in your facebook chatbot works:
#app.route('/', methods=['POST'])
def webhook(): # endpoint for processing incoming messaging events
data = request.get_json()
if data["object"] == "page":
for entry in data["entry"]:
for messaging_event in entry["messaging"]:
if messaging_event["message"].get("attachments"):
attachment_link = messaging_event["message"]["attachments"][0]["payload"]["url"]
print("Image received, boss!")
print(attachment_link)
good chatbot-thing!
Marco
In PHP,
When user sents it to bot, below response we get which contains attachement type and url
{
"object": "page",
"entry": [
{
"id": "000000000000000",
"time": 1511956708068,
"messaging": [
{
"sender": {
"id": "000000000000000"
},
"recipient": {
"id": "000000000000000"
},
"timestamp": 1511956707862,
"message": {
"mid": "mid.$xxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
"seq": 42172,
"sticker_id": 369239263222822,
"attachments": [
{
"type": "image",
"payload": {
"url": "https:\/\/scontent.xx.fbcdn.net\/v\/t39.1997-6\/851557_369239266556155_759568595_n.png?_nc_ad=z-m&_nc_cid=0&oh=9058fb52f628d0a6ab92f85ea310db0a&oe=5A9DAADC",
"sticker_id": 369239263222822
}
}
]
}
}
]
}
]
}
This is how you get different type of messages from user
//get the response from user
$input = json_decode(file_get_contents('php://input'), true);
//first check if attachment is present
$attachment = array_key_exists('attachments', $input['entry'][0]['messaging'][0]['message']);
//get the attachement type and url
$type = $input['entry'][0]['messaging'][0]['message']['attachments'][0]['type'];
$file_url = $input['entry'][0]['messaging'][0]['message']['attachments'][0]['payload']['url'];
Hope this helps you
https://developers.facebook.com/docs/messenger-platform/implementation#receive_message
Check this link out.
It says that,
"Messages may have an image, video or audio attachment."
UPDATE:
The above link is broken as Facebook recently updated their documentations in a weirdly downgraded version with many contents missing.
To elaborate as pointed out in the comment, when a user sends a request, your server will receive such a json:
{
"mid": "some mid",
"seq": 26,
"attachments": [{
"type": "image",
"payload": {
"url": "some image url"
}
}]
}
and you can maybe create a download function to download the image to your server.
To use this data, as mentioned above, you can use the webhook.
app.post('/webhook', function (req, res) {
var data = req.body;
// Make sure this is a page subscription
if (data.object == 'page') {
console.log(data.entry);
// Iterate over each entry
// There may be multiple if batched
data.entry.forEach(function(pageEntry) {
var pageID = pageEntry.id;
var timeOfEvent = pageEntry.time;
// Iterate over each messaging event
pageEntry.messaging.forEach(function(messagingEvent) {
receivedMessage(messagingEvent);
});
});
// Assume all went well.
//
// You must send back a 200, within 20 seconds, to let us know you've
// successfully received the callback. Otherwise, the request will time out.
res.sendStatus(200);
}
});
function receivedMessage(event) {
var senderID = event.sender.id;
var recipientID = event.recipient.id;
var timeOfMessage = event.timestamp;
var message = event.message;
if (senderID == PAGE_ID) {
console.error("Sender is self.");
return;
}
console.log("Received message for user %d and page %d at %d with message:",
senderID, recipientID, timeOfMessage);
console.log(JSON.stringify(message));
var messageId = message.mid;
// You may get a text or attachment but not both
var messageText = message.text;
var messageAttachments = message.attachments;
if (messageText) {
// If we receive a text message, check to see if it matches any special
// keywords and send back the corresponding example. Otherwise, just echo
// the text we received.
} else if (messageAttachments) {
messageAttachments.forEach(function(messageAttachment) {
var attachmentUrl = messageAttachment.payload.url;
console.log("Received Attachment");
download(attachmentUrl);
}
}
This code was taken from the sample code of Facebook.
Related
I am trying to implement a deferred sending function to my site which currently sends email via Microsoft Graph. I have found some articles about SingleValueLegacyExtendedProperty being used to defer sending, but so far has been unsuccessful with it.
My current code just ignores the deferred sending time and sends the email immediately.
var message = new Message
{
Subject = Subject,
Body = new ItemBody
{
ContentType = BodyType.Html,
Content = bodyText
},
ToRecipients = new List<Recipient>()
{
new Recipient
{
EmailAddress = new EmailAddress
{
Address = recipient
}
}
},
};
message.SingleValueExtendedProperties = new MessageSingleValueExtendedPropertiesCollectionPage
{
new SingleValueLegacyExtendedProperty()
{
Id = "SystemTime 0x3FEF",
Value = DateTimeToSend.ToString("o")
}
};
var saveToSentItems = true;
await graphServiceClient.Me
.SendMail(message, saveToSentItems)
.Request()
.PostAsync();
In this article they suggest that the ID should be String {8ECCC264-6880-4EBE-992F-8888D2EEAA1D} Name pidTagDeferredSendTime when passing as JSON but it looks like that was not successful for other. I checked and can confirm that it did not work for me either.
Its important that the DateTime that you want the message to be sent is in UTC eg
"value": "2022-08-01T23:39:00Z"
Using local time won't work as Exchange does everything in UTC
I am trying to write one Twilio function. Inside the Twilio function, I have one external API call with parameters for one of my API. API will return the result and that result I am passing using "Say" tag.
I have one Twilio Autopilot Bot in which I have one task added. On execution of that task it will call "Action URL" which is the Twilio function URL.
But somehow this full flow is not working. I think my external API call using AXIOS is not proper. Can you help me to call external API with parameters from the Twilio function? For my Twilio function check following code
Thanks in advance
exports.handler = function(context, event, callback) {
const responseData = await axios.post(`API_PATH/GetMessageData`,'Minute':'3000','MessageType':'2,3'});
const resultData = responseData.data;
let response = {};
response.actions = [];
response.actions.push({"say":"hello sam" + resultData})
callback(null,response)
};
You are calling axios using await, but you have not declared the function to be an async function.
You should also ensure to catch any potential API or connectivity errors when making external requests. That will also show if there's an error in calling your API.
exports.handler = async function(context, event, callback) {
try {
const responseData = await axios.post(`API_PATH/GetMessageData`,'Minute':'3000','MessageType':'2,3'});
const resultData = responseData.data;
let response = {};
response.actions = [];
response.actions.push({"say":"hello sam" + resultData})
callback(null,response)
} catch(error) {
console.error(error)
let response = {};
response.actions = [];
response.actions.push({"say":"There was a problem with the bot, please try again."});
callback(null, response);
}
};
Edit
You also added that your result looks like this:
{
"Message": {
"Text": "Data retrieved successfully"
},
"MessageList": [
{ "ContactNo": "+91xxxxxxxx", "Message": "test message", },
{ "ContactNo": "+91xxxxxxxx", "Message": "test message 2", }
]
}
I'm not sure exactly which of those messages are what you want to send back to the user. Perhaps you want to send both of the Messages inside the MessageList object? You could do that like so (just showing the part of the code inside the try):
const responseData = await axios.post(`API_PATH/GetMessageData`,'Minute':'3000','MessageType':'2,3'});
const resultData = responseData.data;
let response = {};
response.actions = [];
resultData.MessageList.forEach((message) => {
response.actions.push({"say": message.Message });
}
callback(null,response)
This loops through the MessageList and adds a new say action to the response with each message.
I have an error in prase JSON data API flutter,
the is the response from API
{
"response": {
"message": "Loaction Found",
"responseCode": 0
},
"Loaction": {
"driver_id": 1,
"Latitude": "31.959727",
"longitude": "35.837615",
"time": "12/04/2020 16:09:33"
}
}
I made the model from the https://javiercbk.github.io/json_to_dart/
but I can't know how to prase the contents of JSON data, I try using the below code, but I didn't receive and data,
can anyone help me ??
this is my all code:
https://github.com/mohmmed750/flutter-json/blob/master/json-flutter
Please remove this code
for (Map i in jsonData) {
_list.add(DriverLocation.fromJson(i));
}
And use this code instead
_list.add(DriverLocation.fromJson(jsonData));
Then you can print in the console using, to see the list items.
for (var i = 0; i < _list.length; i++) {
DriverLocation dl = _list[i];
print(dl.loaction.driverId);
}
You don't need to parse the json with DriverLocation class. You can straight off get the Loaction key from jsonData and parse it with Loaction.fromJson() directly.
Something like this:
var location = jsonData['Loaction'];
_list.add(Loaction.fromJson(location));
Code that I tried out - https://dartpad.dev/63fdc82ea0f6641698d42fcde47811f2
Hope this helps!
In my Thunderbird add-on I want to listen to new incoming emails and process the message body.
So I have written a mailListener and added it to an instance of nsIMsgFolderNotificationService.
The listener works fine and notifies when a mail comes. I get the nsIMsgDBHdr object which was fetched, but I cannot stream the message for the particular folder in the msgAdded function of my mailListener. it hangs, and I cannot even see the message body in the Thunderbird's message pane.
I think the nsISyncStreamListener used to stream the message from the folder waits for OnDataAvailable event which is not yet triggered inside the mailListener's msgAdded function.
Any inputs on how to fetch message body when a new email comes? Below is the code for my mailListener
var newMailListener = {
msgAdded: function(aMsgHdr) {
if( !aMsgHdr.isRead ){
let folder = aMsgHdr.folder;
if(aMsgHdr.recipients == "myemail+special#gmail.com"){
let messenger = Components.classes["#mozilla.org/messenger;1"]
.createInstance(Components.interfaces.nsIMessenger);
let listener = Components.classes["#mozilla.org/network/sync-stream-listener;1"]
.createInstance(Components.interfaces.nsISyncStreamListener);
let uri = aMsgHdr.folder.getUriForMsg(aMsgHdr);
messenger.messageServiceFromURI(uri).streamMessage(uri, listener, null, null, false, "");
let messageBody = aMsgHdr.folder.getMsgTextFromStream(listener.inputStream,
aMsgHdr.Charset,
65536,
32768,
false,
true,
{ });
alert("the message body : " + messageBody);
}
}
}
};
I had a similar problem. The solution I found (not easily) is to use MsgHdrToMimeMessage from mimemsg.js as Gloda is not available yet. This uses the callback function:
var newMailListener = {
msgAdded: function(aMsgHdr) {
if( !aMsgHdr.isRead ){
MsgHdrToMimeMessage(aMsgHdr, null, function (aMsgHdr, aMimeMessage) {
// do something with aMimeMessage:
alert("the message body : " + aMimeMessage.coerceBodyToPlaintext());
//alert(aMimeMessage.allUserAttachments.length);
//alert(aMimeMessage.size);
}, true);
}
}
};
And do not forget to include the necessary module:
Components.utils.import("resource:///modules/gloda/mimemsg.js");
More folow up reading can be found e. g. here.
Do you have any idea? I am developing an app using Unity IDE and C#. Also, I'm using the social networking prime31 for my plugin with Facebook. I was able to get all the graphs and display it in my screen app, but since last week it didn't show the profile picture and my friend's picture, it just shows a plain question mark. Do you have any idea with regard to that?
But I was able to show the username and my friend's username. My app token is working, and I am using JSON data to get the data from the Facebook URL.
void Start()
{
getFB_ID();
}
void getFB_ID()
{
Facebook.instance.graphRequest( "me/", HTTPVerb.GET, ( error, obj ) =>
{
var ht = obj as Hashtable;
userId = ht["id"].ToString();
Debug.Log( "USER ID: " + userId);
string url = "http://graph.facebook.com/"+userId+"?fields=id,name,picture";
StartCoroutine(getURL(url));
});
}
IEnumerator getURL(string url)
{
WWW www = new WWW(url);
yield return www;
Debug.Log ("Heres the URL you are accessing: " + url);
ProfilePicDisplay(www.text);
public void ProfilePicDisplay(string jsonString)
{
JsonData jsonProfilePic = JsonMapper.ToObject(jsonString);
ConverterScript fbprofilepic;
MyPicture = new ArrayList();
{
fbprofilepic = new ConverterScript();
fbprofilepic.name = jsonProfilePic["name"].ToString();
fbprofilepic.picture = jsonProfilePic["picture"].ToString();
LoadProfilePic(fbprofilepic);
MyPicture.Add(fbprofilepic.name);
}
}
private void LoadProfilePic(ConverterScript profile)
{
string ProfilePic = "userAvatar";
GameObject profile_pic_holder = GameObject.Find(ProfilePic);
profile_pic_holder.SendMessage("LoadImage", profile);
}
was able to get the data in my logs, but the problem is it didnt load the image, it says:
You are trying to load data from a www stream which had the following error when downloading.
Could not resolve host: JsonData object (Domain name not found)
As of last week, October 3rd and detailed here: https://developers.facebook.com/blog/post/2012/10/03/platform-updates--operation-developer-love/
The picture endpoint no longer returns the picture URL in the string. It returns a dictionary and you have to change your parsing to get to it. So the data returned will look more like this:
{
"id": "1234567",
"name": "Your Name",
"picture": {
"data": {
"url": "https://fbcdn-profile-a.akamaihd.net/hprofile-ak-prn1/your_picture.jpg",
"is_silhouette": false
}
}
}
In the latest LeanLoader, there is an automatic fix for the newly implimented Facebook endpoint abernathy mentioned, which allows you to load the image directly (with all the parsing of the json and other data handled by the engine). You can easily load profile images like this:
function Start () {
LeanLoader.load("https://graph.facebook.com/DentedPixel/picture?type=large&redirect=false", LLOptions().setOnLoad(onImageLoaded));
}
private function onImageLoaded( tex:Texture2D ){
Debug.Log("Your image texture ready to use! :"+tex);
}
There is also many other features that I think people will find helpful with LeanLoader (including caching of images/text/sound and a built-in JSON parser).
try this- fb sdk version-9.1.0
FB.API ("/me/picture?type=large", HttpMethod.GET, DisplayProfilePic);// API call
void DisplayProfilePic(IGraphResult result)
{
Image profilePic;
if (result.Texture != null)
{
profilePic = image1; // diplaying image
profilePic.sprite = Sprite.Create(result.Texture, new Rect(0, 0, result.Texture.width, result.Texture.height), new Vector2());
}
}