I have recently came across this JS code for Zapier by #ReganStarr to create a "like tweet" action for any given tweet_id. I'm no expert but it sure looks fine (no error messages either), nevertheless, for some reason it doesn't work!
Would appreciate a lot if an experienced Zapier + JS eye can identify why isn't it working.
here is the code:
var twitterApplicationConsumerKey = 'MyTwitterConsumerKey';
var twitterApplicationConsumerSecret = 'MyTwitterConsumerSecret';
var twitterApplicationAccessToken = 'MyTwitterAccessToken';
var twitterApplicationAccessTokenSecret = 'MyTwitterTokenSecret';
// That's it. No need to edit anything below.
function b64_hmac_sha1(k,d,_p,_z){
if(!_p){_p='=';}if(!_z){_z=8;}function _f(t,b,c,d){if(t<20){return(b&c)|((~b)&d);}if(t<40){return b^c^d;}if(t<60){return(b&c)|(b&d)|(c&d);}return b^c^d;}function _k(t){return(t<20)?1518500249:(t<40)?1859775393:(t<60)?-1894007588:-899497514;}function _s(x,y){var l=(x&0xFFFF)+(y&0xFFFF),m=(x>>16)+(y>>16)+(l>>16);return(m<<16)|(l&0xFFFF);}function _r(n,c){return(n<<c)|(n>>>(32-c));}function _c(x,l){x[l>>5]|=0x80<<(24-l%32);x[((l+64>>9)<<4)+15]=l;var w=[80],a=1732584193,b=-271733879,c=-1732584194,d=271733878,e=-1009589776;for(var i=0;i<x.length;i+=16){var o=a,p=b,q=c,r=d,s=e;for(var j=0;j<80;j++){if(j<16){w[j]=x[i+j];}else{w[j]=_r(w[j-3]^w[j-8]^w[j-14]^w[j-16],1);}var t=_s(_s(_r(a,5),_f(j,b,c,d)),_s(_s(e,w[j]),_k(j)));e=d;d=c;c=_r(b,30);b=a;a=t;}a=_s(a,o);b=_s(b,p);c=_s(c,q);d=_s(d,r);e=_s(e,s);}return[a,b,c,d,e];}function _b(s){var b=[],m=(1<<_z)-1;for(var i=0;i<s.length*_z;i+=_z){b[i>>5]|=(s.charCodeAt(i/8)&m)<<(32-_z-i%32);}return b;}function _h(k,d){var b=_b(k);if(b.length>16){b=_c(b,k.length*_z);}var p=[16],o=[16];for(var i=0;i<16;i++){p[i]=b[i]^0x36363636;o[i]=b[i]^0x5C5C5C5C;}var h=_c(p.concat(_b(d)),512+d.length*_z);return _c(o.concat(h),512+160);}function _n(b){var t="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",s='';for(var i=0;i<b.length*4;i+=3){var r=(((b[i>>2]>>8*(3-i%4))&0xFF)<<16)|(((b[i+1>>2]>>8*(3-(i+1)%4))&0xFF)<<8)|((b[i+2>>2]>>8*(3-(i+2)%4))&0xFF);for(var j=0;j<4;j++){if(i*8+j*6>b.length*32){s+=_p;}else{s+=t.charAt((r>>6*(3-j))&0x3F);}}}return s;}function _x(k,d){return _n(_h(k,d));}return _x(k,d);
}
var tweetId = input.tweet_id;
//create nonce
function generateRandomString(desiredLengthOfRandomString) {
var result = '';
var possibleCharactersForRandomString = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
for( var i=0; i < desiredLengthOfRandomString; i++ )
result += possibleCharactersForRandomString.charAt(Math.floor(Math.random() * possibleCharactersForRandomString.length));
return result;
}
var randomString = generateRandomString(32);
var nonce = new Buffer(randomString).toString('base64');
//create timestamp
var timestamp = Math.floor(new Date() / 1000);
//create the signature
var signatureParameterString = 'id=' + tweetId + '&oauth_consumer_key=' + twitterApplicationConsumerKey + '&oauth_nonce=' + encodeURIComponent(nonce) + '&oauth_signature_method=HMAC-SHA1&oauth_timestamp=' + timestamp + '&oauth_token=' + twitterApplicationAccessToken + '&oauth_version=1.0';
var signatureBaseString = 'POST&https%3A%2F%2Fapi.twitter.com%2F1.1%2Ffavorites%2Fcreate.json&' + encodeURIComponent(signatureParameterString);
var signingKey = encodeURIComponent(twitterApplicationConsumerSecret) + '&' + encodeURIComponent(twitterApplicationAccessTokenSecret);
var signature = b64_hmac_sha1(signingKey, signatureBaseString);
var apiUrl = 'https://api.twitter.com/1.1/favorites/create.json?id=' + tweetId;
var oauthString = 'OAuth oauth_consumer_key="' + twitterApplicationConsumerKey + '", oauth_nonce="' + encodeURIComponent(nonce) + '", oauth_signature="' + encodeURIComponent(signature) + '", oauth_signature_method="HMAC-SHA1", oauth_timestamp="' + timestamp + '", oauth_token="' + twitterApplicationAccessToken + '", oauth_version="1.0"';
fetch(apiUrl, {
method: 'POST',
headers: {
'Authorization': oauthString
}
})
.then(function(res) {
return res.json();
})
.then(function(body) {
var output = body;
callback(null, output);
})
.catch(callback);
Thanks :-)
I just tried the code you posted and it worked for me.
You might double-check that you have your Access Levels set to "read and write" for your app at https://apps.twitter.com/ so that the 4 variables you include at the top of your code have the correct permissions.
And also make sure that you pass in tweet_id in the Input Data of the Zapier code step. (screenshot)
Related
I am trying to query Azure Table storage without using NodeJS. If I run the query on the whole table (sales) I get all the results fine, but when I want to filter on Partition Key and RowKey I get the error "Server failed to authenticate the request. Make sure the value of Authorization header is formed correctly including the signature"
Here is my code
var storageAccount = 'xxxxxxxxx';
var accountKey = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx';
var date = new Date();
var UTCString = date.toUTCString();
var dataToEncode = UTCString + "\n" + "/" + storageAccount + "/sales";
var hash = CryptoJS.HmacSHA256(dataToEncode, CryptoJS.enc.Base64.parse(accountKey));
var strSignature = CryptoJS.enc.Base64.stringify(hash);
var auth = "SharedKeyLite " + storageAccount + ":" + strSignature;
var tableName = 'sales';
var pk ="CAR1748"
var rk = "1";
var queryString = encodeURIComponent(tableName + "(PartitionKey='" + pk + "',RowKey='" + rk + "')");
var path = "https://" + storageAccount + ".table.core.windows.net/" + queryString ;
var header = { "Accept" : "application/json;odata=nometadata", "x-ms-date" : UTCString , "Authorization" : auth , "x-ms-version": "2021-06-08", "DataServiceVersion": "3.0;NetFx","MaxDataServiceVersion": "3.0;NetFx" };
try {
var response = https.get({
url: path,
headers: header
});
context.response.write(response.code);
} catch (e) {
//context.response.write(response.code);
context.response.write(response.body);
return true;
}
Based on the documentation provided here, you would need to include the query string in your data to encode.
So your code would be something like:
var storageAccount = 'xxxxxxxxx';
var accountKey = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx';
var tableName = 'sales';
var pk ="CAR1748"
var rk = "1";
var date = new Date();
var UTCString = date.toUTCString();
var queryString = encodeURIComponent(tableName + "(PartitionKey='" + pk + "',RowKey='" + rk + "')");
var dataToEncode = UTCString + "\n" + "/" + storageAccount + "/" + queryString;
var hash = CryptoJS.HmacSHA256(dataToEncode, CryptoJS.enc.Base64.parse(accountKey));
var strSignature = CryptoJS.enc.Base64.stringify(hash);
var auth = "SharedKeyLite " + storageAccount + ":" + strSignature;
var path = "https://" + storageAccount + ".table.core.windows.net/" + queryString ;
var header = { "Accept" : "application/json;odata=nometadata", "x-ms-date" : UTCString , "Authorization" : auth , "x-ms-version": "2021-06-08", "DataServiceVersion": "3.0;NetFx","MaxDataServiceVersion": "3.0;NetFx" };
try {
var response = https.get({
url: path,
headers: header
});
context.response.write(response.code);
} catch (e) {
//context.response.write(response.code);
context.response.write(response.body);
return true;
}
What I'm trying to achieve is a Zapier Code (JS) action to preform a Twitter reply to a given status ID with a given text .
I'm already using the functioning Zapier (JS) Code action offered by #KayCee which preform a POST favorites/create and would like to modify it so it would preform a reply action to any given status_id using the POST statuses/update (in_reply_to_status_id) as instructed by Twitter API.
Here is #KayCee's code with the modifications I made to preform a reply:
// This code requires that you set the ID of the tweet that you want to reply to as an input variable called "reply_to_id" and the text you wish to reply as an input variable called "status_text". Learn more at https://zapier.com/help/code/#data-variables
// INSTUCTIONS FOR SETTING THESE REQUIRED VARIABLES: After you create a new app at https://apps.twitter.com/, click on the name of the app to open it. Then, select the "Keys and Access Tokens" tab.
var twitterApplicationConsumerKey = 'CONSUMERKEY';
var twitterApplicationConsumerSecret = 'CONSUMERSECRET';
var twitterApplicationAccessToken = 'ACCESSTOKEN';
var twitterApplicationAccessTokenSecret = 'ACCESSTOKENSECRET';
// That's it. No need to edit anything below.
function b64_hmac_sha1(k,d,_p,_z){
if(!_p){_p='=';}if(!_z){_z=8;}function _f(t,b,c,d){if(t<20){return(b&c)|((~b)&d);}if(t<40){return b^c^d;}if(t<60){return(b&c)|(b&d)|(c&d);}return b^c^d;}function _k(t){return(t<20)?1518500249:(t<40)?1859775393:(t<60)?-1894007588:-899497514;}function _s(x,y){var l=(x&0xFFFF)+(y&0xFFFF),m=(x>>16)+(y>>16)+(l>>16);return(m<<16)|(l&0xFFFF);}function _r(n,c){return(n<<c)|(n>>>(32-c));}function _c(x,l){x[l>>5]|=0x80<<(24-l%32);x[((l+64>>9)<<4)+15]=l;var w=[80],a=1732584193,b=-271733879,c=-1732584194,d=271733878,e=-1009589776;for(var i=0;i<x.length;i+=16){var o=a,p=b,q=c,r=d,s=e;for(var j=0;j<80;j++){if(j<16){w[j]=x[i+j];}else{w[j]=_r(w[j-3]^w[j-8]^w[j-14]^w[j-16],1);}var t=_s(_s(_r(a,5),_f(j,b,c,d)),_s(_s(e,w[j]),_k(j)));e=d;d=c;c=_r(b,30);b=a;a=t;}a=_s(a,o);b=_s(b,p);c=_s(c,q);d=_s(d,r);e=_s(e,s);}return[a,b,c,d,e];}function _b(s){var b=[],m=(1<<_z)-1;for(var i=0;i<s.length*_z;i+=_z){b[i>>5]|=(s.charCodeAt(i/8)&m)<<(32-_z-i%32);}return b;}function _h(k,d){var b=_b(k);if(b.length>16){b=_c(b,k.length*_z);}var p=[16],o=[16];for(var i=0;i<16;i++){p[i]=b[i]^0x36363636;o[i]=b[i]^0x5C5C5C5C;}var h=_c(p.concat(_b(d)),512+d.length*_z);return _c(o.concat(h),512+160);}function _n(b){var t="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",s='';for(var i=0;i<b.length*4;i+=3){var r=(((b[i>>2]>>8*(3-i%4))&0xFF)<<16)|(((b[i+1>>2]>>8*(3-(i+1)%4))&0xFF)<<8)|((b[i+2>>2]>>8*(3-(i+2)%4))&0xFF);for(var j=0;j<4;j++){if(i*8+j*6>b.length*32){s+=_p;}else{s+=t.charAt((r>>6*(3-j))&0x3F);}}}return s;}function _x(k,d){return _n(_h(k,d));}return _x(k,d);
}
var replyToId = input.reply_to_id;
var status = input.status_text;
//create nonce
function generateRandomString(desiredLengthOfRandomString) {
var result = '';
var possibleCharactersForRandomString = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
for( var i=0; i < desiredLengthOfRandomString; i++ )
result += possibleCharactersForRandomString.charAt(Math.floor(Math.random() * possibleCharactersForRandomString.length));
return result;
}
var randomString = generateRandomString(32);
var nonce = new Buffer(randomString).toString('base64');
//create timestamp
var timestamp = Math.floor(new Date() / 1000);
//create the signature
var signatureParameterString = 'in_reply_to_status_id=' + replyToId + '&status=' + status + '&oauth_consumer_key=' + twitterApplicationConsumerKey + '&oauth_nonce=' + encodeURIComponent(nonce) + '&oauth_signature_method=HMAC-SHA1&oauth_timestamp=' + timestamp + '&oauth_token=' + twitterApplicationAccessToken + '&oauth_version=1.0';
var signatureBaseString = 'POST&https%3A%2F%2Fapi.twitter.com%2F1.1%2Fstatuses%2Fupdate.json&' + encodeURIComponent(signatureParameterString);
var signingKey = encodeURIComponent(twitterApplicationConsumerSecret) + '&' + encodeURIComponent(twitterApplicationAccessTokenSecret);
var signature = b64_hmac_sha1(signingKey, signatureBaseString);
var apiUrl = 'https://api.twitter.com/1.1/statuses/update.json?in_reply_to_status_id=' + replyToId + '&status=' + status;
var oauthString = 'OAuth oauth_consumer_key="' + twitterApplicationConsumerKey + '", oauth_nonce="' + encodeURIComponent(nonce) + '", oauth_signature="' + encodeURIComponent(signature) + '", oauth_signature_method="HMAC-SHA1", oauth_timestamp="' + timestamp + '", oauth_token="' + twitterApplicationAccessToken + '", oauth_version="1.0"';
fetch(apiUrl, {
method: 'POST',
headers: {
'Authorization': oauthString
}
})
.then(function(res) {
return res.json();
})
.then(function(body) {
var output = body;
callback(null, output);
})
.catch(callback);
For some reason, I keep on getting error message: "Could not authenticate you" although the same code worked for performing a "like".
Not sure what am I doing wrong?
This JS code for Zapier by #ReganStarr enables to generate a "like" action for any given tweet_id passed as a variable. I'm trying to modify it to generate a "retweet" action.
var twitterApplicationConsumerKey = 'MyTwitterConsumerKey';
var twitterApplicationConsumerSecret = 'MyTwitterConsumerSecret';
var twitterApplicationAccessToken = 'MyTwitterAccessToken';
var twitterApplicationAccessTokenSecret = 'MyTwitterTokenSecret';
// That's it. No need to edit anything below.
function b64_hmac_sha1(k,d,_p,_z){
if(!_p){_p='=';}if(!_z){_z=8;}function _f(t,b,c,d){if(t<20){return(b&c)|((~b)&d);}if(t<40){return b^c^d;}if(t<60){return(b&c)|(b&d)|(c&d);}return b^c^d;}function _k(t){return(t<20)?1518500249:(t<40)?1859775393:(t<60)?-1894007588:-899497514;}function _s(x,y){var l=(x&0xFFFF)+(y&0xFFFF),m=(x>>16)+(y>>16)+(l>>16);return(m<<16)|(l&0xFFFF);}function _r(n,c){return(n<<c)|(n>>>(32-c));}function _c(x,l){x[l>>5]|=0x80<<(24-l%32);x[((l+64>>9)<<4)+15]=l;var w=[80],a=1732584193,b=-271733879,c=-1732584194,d=271733878,e=-1009589776;for(var i=0;i<x.length;i+=16){var o=a,p=b,q=c,r=d,s=e;for(var j=0;j<80;j++){if(j<16){w[j]=x[i+j];}else{w[j]=_r(w[j-3]^w[j-8]^w[j-14]^w[j-16],1);}var t=_s(_s(_r(a,5),_f(j,b,c,d)),_s(_s(e,w[j]),_k(j)));e=d;d=c;c=_r(b,30);b=a;a=t;}a=_s(a,o);b=_s(b,p);c=_s(c,q);d=_s(d,r);e=_s(e,s);}return[a,b,c,d,e];}function _b(s){var b=[],m=(1<<_z)-1;for(var i=0;i<s.length*_z;i+=_z){b[i>>5]|=(s.charCodeAt(i/8)&m)<<(32-_z-i%32);}return b;}function _h(k,d){var b=_b(k);if(b.length>16){b=_c(b,k.length*_z);}var p=[16],o=[16];for(var i=0;i<16;i++){p[i]=b[i]^0x36363636;o[i]=b[i]^0x5C5C5C5C;}var h=_c(p.concat(_b(d)),512+d.length*_z);return _c(o.concat(h),512+160);}function _n(b){var t="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",s='';for(var i=0;i<b.length*4;i+=3){var r=(((b[i>>2]>>8*(3-i%4))&0xFF)<<16)|(((b[i+1>>2]>>8*(3-(i+1)%4))&0xFF)<<8)|((b[i+2>>2]>>8*(3-(i+2)%4))&0xFF);for(var j=0;j<4;j++){if(i*8+j*6>b.length*32){s+=_p;}else{s+=t.charAt((r>>6*(3-j))&0x3F);}}}return s;}function _x(k,d){return _n(_h(k,d));}return _x(k,d);
}
var tweetId = input.tweet_id;
//create nonce
function generateRandomString(desiredLengthOfRandomString) {
var result = '';
var possibleCharactersForRandomString = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
for( var i=0; i < desiredLengthOfRandomString; i++ )
result += possibleCharactersForRandomString.charAt(Math.floor(Math.random() * possibleCharactersForRandomString.length));
return result;
}
var randomString = generateRandomString(32);
var nonce = new Buffer(randomString).toString('base64');
//create timestamp
var timestamp = Math.floor(new Date() / 1000);
//create the signature
var signatureParameterString = 'id=' + tweetId + '&oauth_consumer_key=' + twitterApplicationConsumerKey + '&oauth_nonce=' + encodeURIComponent(nonce) + '&oauth_signature_method=HMAC-SHA1&oauth_timestamp=' + timestamp + '&oauth_token=' + twitterApplicationAccessToken + '&oauth_version=1.0';
var signatureBaseString = 'POST&https%3A%2F%2Fapi.twitter.com%2F1.1%2Ffavorites%2Fcreate.json&' + encodeURIComponent(signatureParameterString);
var signingKey = encodeURIComponent(twitterApplicationConsumerSecret) + '&' + encodeURIComponent(twitterApplicationAccessTokenSecret);
var signature = b64_hmac_sha1(signingKey, signatureBaseString);
var apiUrl = 'https://api.twitter.com/1.1/favorites/create.json?id=' + tweetId;
var oauthString = 'OAuth oauth_consumer_key="' + twitterApplicationConsumerKey + '", oauth_nonce="' + encodeURIComponent(nonce) + '", oauth_signature="' + encodeURIComponent(signature) + '", oauth_signature_method="HMAC-SHA1", oauth_timestamp="' + timestamp + '", oauth_token="' + twitterApplicationAccessToken + '", oauth_version="1.0"';
fetch(apiUrl, {
method: 'POST',
headers: {
'Authorization': oauthString
}
})
.then(function(res) {
return res.json();
})
.then(function(body) {
var output = body;
callback(null, output);
})
.catch(callback);
I thought that by modifying this line:
var apiUrl = 'https://api.twitter.com/1.1/favorites/create.json?id=' + tweetId;
to this:
var apiUrl = 'https://api.twitter.com/1.1/statuses/' + tweetId +'.json';
as instructed by Twitter here, would be enough but it doesn't work :-(
What am I doing wrong?
I believe the endpoint mentioned on Twitter is different than the one you've changed it to. Could you try changing the apiUrl to the following?
var apiUrl = 'https://api.twitter.com/1.1/statuses/retweet/' + tweetId +'.json';
or (for better readability)
var apiUrl = `https://api.twitter.com/1.1/statuses/retweet/${tweetId}.json`;
I haven't tested this but it looks like the cause of the issue. Please also post the error you get in case this fails.
UPDATE:
The SignatureBaseString and the SignatureParameterString need to be changed as well.
var twitterApplicationConsumerKey = 'MyTwitterConsumerKey';
var twitterApplicationConsumerSecret = 'MyTwitterConsumerSecret';
var twitterApplicationAccessToken = 'MyTwitterAccessToken';
var twitterApplicationAccessTokenSecret = 'MyTwitterTokenSecret';
// That's it. No need to edit anything below.
function b64_hmac_sha1(k,d,_p,_z){
if(!_p){_p='=';}if(!_z){_z=8;}function _f(t,b,c,d){if(t<20){return(b&c)|((~b)&d);}if(t<40){return b^c^d;}if(t<60){return(b&c)|(b&d)|(c&d);}return b^c^d;}function _k(t){return(t<20)?1518500249:(t<40)?1859775393:(t<60)?-1894007588:-899497514;}function _s(x,y){var l=(x&0xFFFF)+(y&0xFFFF),m=(x>>16)+(y>>16)+(l>>16);return(m<<16)|(l&0xFFFF);}function _r(n,c){return(n<<c)|(n>>>(32-c));}function _c(x,l){x[l>>5]|=0x80<<(24-l%32);x[((l+64>>9)<<4)+15]=l;var w=[80],a=1732584193,b=-271733879,c=-1732584194,d=271733878,e=-1009589776;for(var i=0;i<x.length;i+=16){var o=a,p=b,q=c,r=d,s=e;for(var j=0;j<80;j++){if(j<16){w[j]=x[i+j];}else{w[j]=_r(w[j-3]^w[j-8]^w[j-14]^w[j-16],1);}var t=_s(_s(_r(a,5),_f(j,b,c,d)),_s(_s(e,w[j]),_k(j)));e=d;d=c;c=_r(b,30);b=a;a=t;}a=_s(a,o);b=_s(b,p);c=_s(c,q);d=_s(d,r);e=_s(e,s);}return[a,b,c,d,e];}function _b(s){var b=[],m=(1<<_z)-1;for(var i=0;i<s.length*_z;i+=_z){b[i>>5]|=(s.charCodeAt(i/8)&m)<<(32-_z-i%32);}return b;}function _h(k,d){var b=_b(k);if(b.length>16){b=_c(b,k.length*_z);}var p=[16],o=[16];for(var i=0;i<16;i++){p[i]=b[i]^0x36363636;o[i]=b[i]^0x5C5C5C5C;}var h=_c(p.concat(_b(d)),512+d.length*_z);return _c(o.concat(h),512+160);}function _n(b){var t="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",s='';for(var i=0;i<b.length*4;i+=3){var r=(((b[i>>2]>>8*(3-i%4))&0xFF)<<16)|(((b[i+1>>2]>>8*(3-(i+1)%4))&0xFF)<<8)|((b[i+2>>2]>>8*(3-(i+2)%4))&0xFF);for(var j=0;j<4;j++){if(i*8+j*6>b.length*32){s+=_p;}else{s+=t.charAt((r>>6*(3-j))&0x3F);}}}return s;}function _x(k,d){return _n(_h(k,d));}return _x(k,d);
}
var tweetId = inputData.tweet_id;
//create nonce
function generateRandomString(desiredLengthOfRandomString) {
var result = '';
var possibleCharactersForRandomString = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
for( var i=0; i < desiredLengthOfRandomString; i++ )
result += possibleCharactersForRandomString.charAt(Math.floor(Math.random() * possibleCharactersForRandomString.length));
return result;
}
var randomString = generateRandomString(32);
var nonce = new Buffer(randomString).toString('base64');
//create timestamp
var timestamp = Math.floor(new Date() / 1000);
//create the signature
var signatureParameterString = 'oauth_consumer_key=' + twitterApplicationConsumerKey + '&oauth_nonce=' + encodeURIComponent(nonce) + '&oauth_signature_method=HMAC-SHA1&oauth_timestamp=' + timestamp + '&oauth_token=' + twitterApplicationAccessToken + '&oauth_version=1.0';
var signatureBaseString = `POST&https%3A%2F%2Fapi.twitter.com%2F1.1%2Fstatuses%2Fretweet%2F${tweetId}.json&` + encodeURIComponent(signatureParameterString);
var signingKey = encodeURIComponent(twitterApplicationConsumerSecret) + '&' + encodeURIComponent(twitterApplicationAccessTokenSecret);
var signature = b64_hmac_sha1(signingKey, signatureBaseString);
// var apiUrl = 'https://api.twitter.com/1.1/favorites/create.json?id=' + tweetId;
var apiUrl = `https://api.twitter.com/1.1/statuses/retweet/${tweetId}.json`;
var oauthString = 'OAuth oauth_consumer_key="' + twitterApplicationConsumerKey + '", oauth_nonce="' + encodeURIComponent(nonce) + '", oauth_signature="' + encodeURIComponent(signature) + '", oauth_signature_method="HMAC-SHA1", oauth_timestamp="' + timestamp + '", oauth_token="' + twitterApplicationAccessToken + '", oauth_version="1.0"';
fetch(apiUrl, {
method: 'POST',
headers: {
'Authorization': oauthString
}
})
.then(function(res) {
return res.json();
})
.then(function(body) {
var output = body;
console.log(output);
callback(null, output);
})
.catch(callback);
I need to send HTTP request to AWS with signed request via Javascript. Sadly I cannot use the AWS SDK JS as its either for Node.js or browser, but I need to run it from Rhino JS environment.
seems I am doing something very wrong as I get whatever I do same result - AWS was not able to validate the provided access credentials.
:(
The code I am using is same as the one Amazons is using as example (but in Python). I am using only one external lib so I can use HMCA &SHA.
Any help is much appreciated (and needed as I am struggling for days by now...), so yeah - help!
Thanks is advance!
Cheers,
Joro
gs.include('jshashes');
var method = 'GET';
var service = 'ec2';
var host = 'ec2.amazonaws.com';
var region = 'us-east-1';
var endpoint = 'https://ec2.amazonaws.com';
var access_key = 'ACCESSKEY';
var secret_key = 'SECRET/KEY';
var request_parameters = 'AWSAccessKeyId' + access_key + 'Action=RunInstances&&ImageId=ami-b770fbd8';
function getSignatureKey(key, date, region, service){
var newKey = "AWS4" + key;
var kDate = new Hashes.SHA256().b64_hmac(newKey, date);
var kRegion = new Hashes.SHA256().b64_hmac(kDate, region);
var kService = new Hashes.SHA256().b64_hmac(kRegion, service);
var kSigning = new Hashes.SHA256().b64_hmac(kService, "aws4_request");
return kSigning;
}
var gdt = new GlideDateTime();
var datestamp = gdt.getDate().getByFormat('yyyyMMdd') + 'T' +
gdt.getTime().getByFormat('HHmmss') + 'Z';
var amzdate = gdt.getDate().getByFormat('yyyyMMdd')+"";
var canonical_uri = '/';
var canonical_querystring = request_parameters;
var canonical_headers = 'host:' + host + '\n' + 'x-amz-date:' + amzdate + '\n'
var signed_headers = 'host;x-amz-date';
var payload_hash = new Hashes.SHA256().hex("");
var canonical_request = method + '\n' + canonical_uri + '\n' + canonical_querystring + '\n' + canonical_headers + '\n' + signed_headers + '\n' + payload_hash;
var algorithm = 'AWS4-HMAC-SHA256';
var credential_scope = datestamp + '/' + region + '/' + service + '/' + 'aws4_request';
var string_to_sign = algorithm + '\n' + amzdate + '\n' + credential_scope + '\n' + new Hashes.SHA256().hex(canonical_request);
var signing_key = getSignatureKey(secret_key, datestamp, region, service);
//Python
//var signature = hmac.new(signing_key, (string_to_sign).encode('utf-8'), hashlib.sha256).hexdigest()
var signature = new Hashes.SHA256().hex_hmac(signing_key, string_to_sign);
var authorization_header = algorithm + ' ' + 'Credential=' + access_key + '/' + credential_scope + ', ' + 'SignedHeaders=' + signed_headers + ', ' + 'Signature=' + signature
var headers = {'x-amz-date':amzdate, 'Authorization':authorization_header}
var request_url = endpoint + '?' + canonical_querystring
var httpRequest = new GlideHTTPRequest(request_url);
httpRequest.setRequestHeader(headers);
var res = httpRequest.get();
gs.print(res.statusCode);
gs.print(res.allHeaders);
gs.print(res.body);
Check the URL construction. For one, the request_parameters have some missing and misplaced delimiters.
var request_parameters = 'AWSAccessKeyId=' + access_key +
'&Action=RunInstances&ImageId=ami-b770fbd8';
In addition to inspecting and testing the resulting URL, you might also try to simply the syntax to make it easier to check and update. Just as an example, the following
var credential_scope = datestamp + '/' + region + '/' + service + '/' + 'aws4_request';
var string_to_sign = algorithm + '\n' + amzdate + '\n' + credential_scope + '\n' + new Hashes.SHA256().hex(canonical_request);
could be written as follows (which seems easier to check to me):
var credential_scope = [
datestamp,
region,
service,
'aws4_request'
].join('/');
var string_to_sign = [
algorithm,
amzdate,
credential_scope,
new Hashes.SHA256().hex(canonical_request)
].join('\n');
I am trying to access hourly info from a weather API.
The problem is its not quite working for me, and I am not 100% sure of how to gain access to the information.
This is the site I am working with, and the page on the hourly info.
http://www.wunderground.com/weather/api/d/docs?d=data/hourly&MR=1
I have a strong feeling it has to do with the way the access to variables...
This is my code:
<script>
jQuery(document).ready(function($) {
$.ajax({
url: "http://api.wunderground.com/api/6368023a57d122c7/geolookup/conditions/q/DominicanRepublic/Barahona.json",
dataType : "jsonp",
success : function(parsed_json) {
//get the hourly info -- cant get hourly to work...
var month = parsed_json['hourly_forecast']['FCTTIME']['mon_padded'];
var day = parsed_json['hourly_forecast']['FCTTIME']['mday_padded'];
var year = parsed_json['hourly_forecast']['FCTTIME']['year'];
var time = parsed_json['hourly_forecast']['FCTTIME']['civil'];
var updated = month + "/" + day + "/" + year + " " + time;
var weather = parsed_json['hourly_forecast']['condition'];
var temp = parsed_json['hourly_forecast']['temp']['metric'];
var humid = parsed_json['hourly_forecast']['humidity'];
var wind_direction = parsed_json['hourly_forecast']['wdir']['dir'];
var wind_speed = parsed_json['hourly_forecast']['wspd']['metric'];
var wind_string = wind_direction + " " + wind_speed + " Km/h";
document.getElementById("weather").innerHTML = weather;
document.getElementById("temp").innerHTML = temp;
document.getElementById("hum").innerHTML = humid;
document.getElementById("wind").innerHTML = wind_string;
}
});
});
</script>
If you open the JSON file from that URL you will see that it does not contain "hourly_forecast" or "FCTTIME".
EDIT:
Open up the JSON file that you are downloading and look at what fields it is sending back to you. JQuery already does the hard part and parses it into an object model. Also, the javascript debuggers in Chrome is great at showing you the JSON object model. You can just set a breakpoint at the beginning of the "success" function and use the "Local Variables" window to explore the JSON object.
Here's your code after I updated it to use the correct field names from the JSON file...
<script>
jQuery(document).ready(function ($) {
$.ajax({
url: "http://api.wunderground.com/api/6368023a57d122c7/geolookup/conditions/q/DominicanRepublic/Barahona.json",
dataType: "jsonp",
success: function (parsed_json) {
var current_observation = parsed_json.current_observation;
var lastUpdated = current_observation.observation_time;
var weather = current_observation.weather;
var temp = current_observation.temp_c;
var humid = current_observation.relative_humidity;
var wind_direction = current_observation.wind_dir;
var wind_speed = current_observation.wind_kph;
var wind_string = wind_direction + " " + wind_speed + " Km/h";
alert("Weather: " + weather + "\n"
+ "Temp: " + temp + "\n"
+ "Humidity: " + humid + "\n"
+ "Wind: " + wind_string + "\n"
+ lastUpdated
);
}
});
});
</script>