Created
August 29, 2012 14:11
-
-
Save joemccann/3513142 to your computer and use it in GitHub Desktop.
node twitter oauth hell.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// This is in the same file in my node app, but split so you can see what is being used where | |
pipeToTwitter: function(echo, req, res){ | |
// TODO: Not sure if this check goes here or in pipePhotoToTwiter() in twitter.js plugin | |
if(!req.session.twitter.oauth){ | |
res.type('text/plain') | |
return res.status(403).send("You are not authenticated with Facebook.") | |
} | |
// TODO: EVENTUALLY WE WILL NEED TO CHECK THE | |
// https://api.twitter.com/1/help/configuration.json | |
// RESPONSE THAT CONTAINS SHORT URL CHARS AND MAX MEDIA UPLOADS | |
// SEE https://dev.twitter.com/docs/api/1/get/help/configuration | |
var oauth = req.session.twitter.oauth | |
var uri = 'https://upload.twitter.com/1/statuses/update_with_media.json' | |
var method = 'POST' | |
var authHeaders = createAuthHeaders(oauth, uri, method ) | |
console.dir(echo) | |
console.dir(authHeaders) | |
var command = 'curl --request \'POST\' \'https://upload.twitter.com/1/statuses/update_with_media.json\' '+ | |
'--header \''+authHeaders+'\' -F "media[]=@'+echo.fullPhotoPath+'" -F "status='+echo.caption+'" --header "Expect: "' | |
console.log('\n\n'+command+'\n\n') | |
exec(command, function(err,data){ | |
if(err) { | |
console.error(err) | |
return res.json(err) | |
} | |
if(data) { | |
console.dir(data,8) | |
// NOTE: If the user tries to exceed the number of updates allowed, | |
// this method will also return an HTTP 403 error, similar to POST statuses/update. | |
// TODO: CHECK FOR THIS!! | |
return res.json(JSON.parse(data)) | |
} | |
}) // end exec() | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var fs = require('fs') | |
, path = require('path') | |
, request = require('request') | |
, qs = require('querystring') | |
, exec = require('child_process').exec | |
, crypto = require('crypto') | |
var twitter_config = JSON.parse( fs.readFileSync( path.resolve(__dirname, 'twitter-config.json'), 'utf-8' ) ) | |
function uuid(){ | |
var s = [], itoh = '0123456789ABCDEF'; | |
// Make array of random hex digits. The UUID only has 32 digits in it, but we | |
// allocate an extra items to make room for the '-'s we'll be inserting. | |
for (var i = 0; i <36; i++) s[i] = Math.floor(Math.random()*0x10); | |
// Conform to RFC-4122, section 4.4 | |
s[14] = 4; // Set 4 high bits of time_high field to version | |
s[19] = (s[19] & 0x3) | 0x8; // Specify 2 high bits of clock sequence | |
// Convert to hex chars | |
for (var i = 0; i <36; i++) s[i] = itoh[s[i]]; | |
// Insert '-'s | |
s[8] = s[13] = s[18] = s[23] = '-'; | |
return s.join(''); | |
} | |
function sha1 (key, body) { | |
return crypto.createHmac('sha1', key).update(body).digest('base64') | |
} | |
function rfc3986 (str) { | |
return encodeURIComponent(str) | |
.replace(/!/g,'%21') | |
.replace(/\*/g,'%2A') | |
.replace(/\(/g,'%28') | |
.replace(/\)/g,'%29') | |
.replace(/'/g,'%27') | |
; | |
} | |
function hmacsign (httpMethod, base_uri, params, consumer_secret, token_secret, body) { | |
// adapted from https://dev.twitter.com/docs/auth/oauth | |
var base = | |
(httpMethod || 'GET') + "&" + | |
encodeURIComponent( base_uri ) + "&" + | |
Object.keys(params).sort().map(function (i) { | |
// big WTF here with the escape + encoding but it's what twitter wants | |
return escape(rfc3986(i)) + "%3D" + escape(rfc3986(params[i])) | |
}).join("%26") | |
var key = encodeURIComponent(consumer_secret) + '&' | |
if (token_secret) key += encodeURIComponent(token_secret) | |
return sha1(key, base) | |
} | |
function createAuthHeaders(_oauth, uri, method){ | |
var form = {} | |
var oa = {} | |
for (var i in form) oa[i] = form[i] | |
for (var i in _oauth) oa['oauth_'+i] = _oauth[i] | |
if (!oa.oauth_version) oa.oauth_version = '1.0' | |
if (!oa.oauth_timestamp) oa.oauth_timestamp = Math.floor( (new Date()).getTime() / 1000 ).toString() | |
if (!oa.oauth_nonce) oa.oauth_nonce = uuid().replace(/-/g, '') | |
oa.oauth_signature_method = 'HMAC-SHA1' | |
var consumer_secret = oa.oauth_consumer_secret | |
delete oa.oauth_consumer_secret | |
var token_secret = oa.oauth_token_secret | |
delete oa.oauth_token_secret | |
var baseurl = uri.protocol + '//' + uri.host + uri.pathname | |
var signature = hmacsign(method, baseurl, oa, consumer_secret, token_secret) | |
// oa.oauth_signature = signature | |
// Not used? | |
for (var i in form) { | |
console.log('i in form '+ i) | |
if ( i.slice(0, 'oauth_') in _oauth) { | |
// skip | |
console.log('skipping') | |
} else { | |
delete oa['oauth_'+i] | |
} | |
} | |
// NOTE: I added a space after the commma in the join() to explicitly match the way Twitter is doing it | |
var authorization = | |
'Authorization: OAuth '+Object.keys(oa).sort().map(function (i) {return i+'="'+rfc3986(oa[i])+'"'}).join(', ') | |
authorization += ', oauth_signature="'+rfc3986(signature)+'"' | |
return authorization | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
curl --request 'POST' 'https://upload.twitter.com/1/statuses/update_with_media.json' --header 'Authorization: OAuth oauth_consumer_key="Q3WlVw5BskIdGouOEZEv2w", oauth_nonce="c6f366d2c9e7b2669fd1d5ece56f61d7", oauth_signature="Ba6IB8uH2SjtrK8a%2FgZnqCgvIKs%3D", oauth_signature_method="HMAC-SHA1", oauth_timestamp="1346207448", oauth_token="14814762-vvYtBOLX8hBAQ0i0f1k4wxrioG1jOk49MJrqn3myE", oauth_version="1.0"' -F "media[][email protected]" -F "status=Test from cURL" --header "Expect: " |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment