3

I'm implementing a bot that uses Facebook's Send API. According to the documentation it is possible to send files using a request. The documentation offers two methods, one sending a URL to the file and the other uploading the file. I don't want to upload the file and give it a URL as this is an open source library that doesn't want to assume anything about the implementation.

I do want to upload the file directly. The documentation for uploading the file uses cURL for the example and looks as follows:

curl  \
  -F recipient='{"id":"USER_ID"}' \
  -F message='{"attachment":{"type":"file", "payload":{}}}' \
  -F filedata=@/tmp/receipt.pdf \
  "https://graph.facebook.com/v2.6/me/messages?access_token=PAGE_ACCESS_TOKEN"    

My current take is that it should look something like this:

facebook_message.access_token = configuration.access_token;
var fileReaderStream = fs.createReadStream('./sampleData.json')
var formData = {
                "recipient": JSON.stringify({
                  "id":message.channel
               }),
               "attachment": JSON.stringify({
                  "type":"file", 
                  "payload":{}
               }),
               "filedata": fileReaderStream
               }

request({
         "method": 'POST',
         "json": true,
         "formData": formData,
         "uri": 'https://graph.facebook.com/v2.6/me/messages?access_token=' + configuration.access_token
        },
        function(err, res, body) {
               //***
        });

When I run this I receive the following response:

{ 
  message: '(#100) Must send either message or state',
  type: 'OAuthException',
  code: 100,
  error_subcode: 2018015,
  fbtrace_id: '***' 
 }
Agam Rafaeli-Farhadian
  • 5,827
  • 3
  • 18
  • 23
  • 1
    you as missing something very important in your question: what exactly does not work? did you debug it? any info in the callback? does it get called? "this is my solution but it does not work" is a bit too broad for stackoverflow. – andyrandy Nov 25 '16 at 22:06
  • Adding that in now. Thank you. – Agam Rafaeli-Farhadian Nov 26 '16 at 13:17

2 Answers2

2

The error you are receiving is because "attachment":{} needs to be inside an object called message. You must send either a message or sender_action object with facebook send API.

var formData = {
                "recipient": JSON.stringify({
                  "id":message.channel
               }),
               "message": JSON.stringify({
               "attachment": {
                  "type":"file",
                  "payload":{}
              }
          }),
               "filedata": fileReaderStream

               }

Facebook should accept your api call after this, however I was unable to display a jpg file sent using your code. Perhaps it will work with your JSON file

Jon Church
  • 2,320
  • 13
  • 23
0

The official example app includes a function for file uploads via URL: https://github.com/fbsamples/messenger-platform-samples/blob/master/node/app.js

This is the relevant function:

function sendFileMessage(recipientId) {
  var messageData = {
    recipient: {
      id: recipientId
    },
    message: {
      attachment: {
        type: "file",
        payload: {
          url: SERVER_URL + "/assets/test.txt"
        }
      }
    }
  };

  callSendAPI(messageData);
}

If you really want to do it the hard way, take a look at the request module docs: https://www.npmjs.com/package/request#forms Check out the example code with "formData" in the section. You are using "form", which seems to be for regular data.

andyrandy
  • 72,880
  • 8
  • 113
  • 130
  • 1
    I explicitly said that I don't want to upload the file. In order to use this example function I have to have a URL for the file. I don't have a URL for the file, and I want to upload it directly. – Agam Rafaeli-Farhadian Nov 25 '16 at 22:03
  • the file must be on the server, so why not use the url instead? why do you not have an url? i don´t get it. – andyrandy Nov 25 '16 at 22:03
  • not sure why you downvoted, i just wanted to help with an easier solution. it´s not a wrong solution anyway, it will work - just with an url. the user will get the file anyway, so why not just do that? – andyrandy Nov 25 '16 at 22:04
  • edited the answer, see the last sentences. it should be formData, not form - at least that´s what the official documentation of the request module says. – andyrandy Nov 25 '16 at 22:16
  • 2
    Not everyone runs Node.js as a web server. It makes prefect sense to upload the file rather than providing a URL. – Brad Nov 26 '16 at 01:03
  • @Brad: did you even read the edited part before downvoting? the last 2 sentences in my answer? i did add information about uploading too. but IF there is node.js on the server, the url version would be a lot easier. – andyrandy Nov 26 '16 at 07:46
  • @luschn What makes you think I downvoted? And yes, I read your answer. – Brad Nov 26 '16 at 07:48
  • then i don´t understand your comment at all. of course not everyone runs node.js as a web server. but he did not say that he does not. he MUST use it on a server, as he is using it for a bot. – andyrandy Nov 26 '16 at 07:49
  • @luschn having a URL for a file means that you must also have a CDN-like system set up. The file could be dynamically produced, like an ad-hoc report for example. – Agam Rafaeli-Farhadian Nov 26 '16 at 12:44
  • Do you happen to have context on how FB uses the provided URL? Does the URL have to always be available? – Agam Rafaeli-Farhadian Nov 26 '16 at 12:44
  • i am not entirely sure, but i believe the url does nothave to be available. if you upload a file to the user or page feed, you can also present an URL and it will be uploaded. so i assume it is the same, which means that you can use a dynamically produces file too and delete it later - for example. although, it should be easy with the request module to upload a file, see the bold text in my answer. you are just using the wrong parameter. – andyrandy Nov 26 '16 at 19:11
  • Direct uploading is the way to go. Already tried with formData and updated the question and it still isn't working. Also have an error ther. – Agam Rafaeli-Farhadian Nov 26 '16 at 20:14
  • did you open the link in my answer? i am not sure what you did there, but you did not follow the docs, did you just replace form with formData? that´s not it, take a look at the example at "multipart/form-data (Multipart Form Uploads)" in the link i posted. – andyrandy Nov 27 '16 at 13:51