131 error code on STATUS get request for upload media


#1

I’m working on twitter video upload script in node and am running into the 131 error (which I haven’t seen solved yet).

Below is the function code I’m using, trying to follow the current documentation for chunk uploading.

Any help would be GREATLY appreciated

fs.stat(filePath, function(err, stats) {
    var formData, normalAppendCallback, options;
    console.log('STAT SIZE', stats.size);
    formData = {
        command: "INIT",
        media_type: 'video/mp4',
        total_bytes: stats.size
    };
    options = {
        url: 'https://upload.twitter.com/1.1/media/upload.json',
        oauth: oauthCredentials,
        formData: formData
    };

    normalAppendCallback = function(media_id) {
        return function(err, response, body) {

            finished++;
            if (finished === segment_index) {
                // console.log(response)
                console.log('CALL FINALIZE')

                options.formData = {
                    command: 'FINALIZE',
                    media_id: media_id
                };
                request.post(options, function(err, response, body) {
                    console.log('FINALIZED',response.statusCode,body);
                    // console.log(response)

                    delete options.formData;

                    //Note: This is not working as expected yet.
                    options.qs = {
                        command: 'STATUS',
                        media_id: media_id
                    };
                    console.log('STATUS OPTIONS', options)
                    setTimeout(function() {
                      request.get(options, function(err, response, body) {
                          console.log('STATUS: ', response.statusCode, body);
                      });
                    }, 120000);
                    
                });
            }
        };
    };


    request.post(options, function(err, response, body) {
        var media_id;
        media_id = JSON.parse(body).media_id_string;
        console.log(media_id)
        fs.open(filePath, 'r', function(err, fd) {
            var bytesRead, data;

            while (offset < stats.size) {
                console.log('tick')
                bytesRead = fs.readSync(fd, theBuffer, 0, bufferLength, null);
                data = bytesRead < bufferLength ? theBuffer.slice(0, bytesRead) : theBuffer;
                options.formData = {
                    command: "APPEND",
                    media_id: media_id,
                    segment_index: segment_index,
                    media_data: data.toString('base64')
                };
                // console.log(options)
                request.post(options, normalAppendCallback(media_id));
                offset += bufferLength;
                segment_index++
            }
        });
    });
});

#2

Hi @digitoole1, to be able to help you w’ll need more information. Can you send the full HTTP request you send to twitter? That would help a lot thanks.


#3

thanks @digital_human. Below is the entire file with the creds removed.

You’ll notice that I started with node-twitter-api and learned that it’s approach to uploading media doesn’t work with Twitter’s API guidelines for uploading video. I then went back to the REST API documentation and started on uploading chunks. I was able to find and adapt the code inside the ‘postAction’ method. Everything appears to be working up to the point of the STATUS step within the chunk upload flow. That’s where i get the 131 response.

Is this enough info?

var Twitter = require("node-twitter-api");
var request = require("request");

var twitter = new Twitter({
    consumerKey: '...',
    consumerSecret: '...',
    callback: 'http://127.0.0.1:8080/twitter-response.html'
});

var _requestSecret;



var bufferLength, filePath, finished, fs, oauthCredentials, offset, request, segment_index, theBuffer;

request = require('request');
fs = require('fs');
filePath = __dirname+'/test.mp4';
bufferLength = 1000000;
theBuffer = new Buffer(bufferLength);
offset = 0;
segment_index = 0;
finished = 0;





module.exports = {
	

  requestTokenAction: function (req, res) {
    console.log('twitter request access token')
    twitter.getRequestToken(function(err, requestToken, requestSecret) {
                if (err)
                    res.status(500).send(err);
                else {
                    _requestSecret = requestSecret;
                    res.redirect("https://api.twitter.com/oauth/authenticate?oauth_token=" + requestToken);
                }
            });
  },
  
  accessTokenAction: function(req, res) {
    console.log('accessTokenAction', req.param('oauth_token'), req.param('oauth_verifier'))
    var requestToken = req.param('oauth_token'),
        verifier = req.param('oauth_verifier');
    twitter.getAccessToken(requestToken, _requestSecret, verifier, function(err, accessToken, accessSecret) {
        if (err)
            res.status(500).send(err);
        else
            twitter.verifyCredentials(accessToken, accessSecret, function(err, user) {
                if (err)
                    res.status(500).send(err);
                else
                    res.json({ access_token: accessToken, access_secret : accessSecret, user: user});
            });
    });
  },

  postAction : function(req, res) {


    var oauthCredentials = {
      consumer_key: '...',
      consumer_secret: '...',
      token: req.param('access_token'),
      token_secret: req.param('access_secret')
    };




    fs.stat(filePath, function(err, stats) {
        var formData, normalAppendCallback, options;
        console.log('STAT SIZE', stats.size);
        formData = {
            command: "INIT",
            media_type: 'video/mp4',
            total_bytes: stats.size
        };
        options = {
            url: 'https://upload.twitter.com/1.1/media/upload.json',
            oauth: oauthCredentials,
            formData: formData
        };

        normalAppendCallback = function(media_id) {
            return function(err, response, body) {

                finished++;
                if (finished === segment_index) {
                    // console.log(response)
                    console.log('CALL FINALIZE')

                    options.formData = {
                        command: 'FINALIZE',
                        media_id: media_id
                    };
                    request.post(options, function(err, response, body) {
                        console.log('FINALIZED',response.statusCode,body);

                        delete options.formData;

                        options.qs = {
                            command: 'STATUS',
                            media_id: media_id
                        };
                        console.log('STATUS OPTIONS', options)
                        setTimeout(function() {
                          request.get(options, function(err, response, body) {
                              console.log('STATUS: ', response.statusCode, body);
                          });
                        }, 120000);
                        
                    });
                }
            };
        };


        request.post(options, function(err, response, body) {
            var media_id;
            media_id = JSON.parse(body).media_id_string;
            console.log(media_id)
            fs.open(filePath, 'r', function(err, fd) {
                var bytesRead, data;

                while (offset < stats.size) {
                    console.log('tick')
                    bytesRead = fs.readSync(fd, theBuffer, 0, bufferLength, null);
                    data = bytesRead < bufferLength ? theBuffer.slice(0, bytesRead) : theBuffer;
                    options.formData = {
                        command: "APPEND",
                        media_id: media_id,
                        segment_index: segment_index,
                        media_data: data.toString('base64')
                    };
                    // console.log(options)
                    request.post(options, normalAppendCallback(media_id));
                    offset += bufferLength;
                    segment_index++
                }
            });
        });
    });






    
    
  }
};

#4

You might notice i have a setTimeout of 2 minutes before STATUS is called on the off chance that the video wasn’t ready yet. But that didn’t fix it.


#5

@andypiper I see a note that you edited my post, but I can’t for the life of me figure out what was changed. Do you have any helpful advice to share?

thanks very much


#6

All I did was to move this from the REST to the Media API category - nothing to add myself at this time I’m afraid.