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++
}
});
});
});
}
};