how to send sms in regional language using nodejs? - javascript

im using textlocal.in api for sending bulk sms, when i type message in regional language it shows error
{"errors":[{"code":204,"message":"Invalid message content"}],"status":"failure"}
is there any way of sending regional language please help me?
var http = require('http');
var urlencode = require('urlencode');
var msg = 'ಅನುವಾದಿಸಿ';
var toNumber = '9731750371';
var username = 'dinesh#cantern.in';
var hash = '171f2176f6a24f1d219028011d5bff7b9eac1a3ff91873de62af429a736da26'; // The hash key could be found under Help->All Documentation->Your hash key. Alternatively you can use your Textlocal password in plain text.
var sender = 'txtlcl';
var data = 'username=' + username + '&hash=' + hash + '&sender=' + sender + '&numbers=' + toNumber + '&message=' + msg;
var options = {
host: 'api.textlocal.in', path: '/send?' + data
};
callback = function (response) {
var str = '';//another chunk of data has been recieved, so append it to `str`
response.on('data', function (chunk) {
str += chunk;
});//the whole response has been recieved, so we just print it out here
response.on('end', function () {
console.log(str);
});
}//console.log('hello js'))
http.request(options, callback).end();

First install
npm install i18n-nodejs --save
download the locale language json file and use this code
var config = {
"lang": "ar",
"langFile": "./../../locale.json"//relative path to index.js file
}
var i18n = require('i18n-nodejs')(config.lang, config.langFile);
where "ar" refers to Arabic language
and set character-set to UTF-8 like this
response.header("Content-Type", "html/text; charset=utf-8");

Related

How to fix "Exception: Limit Exceeded" error when trying to upload an image to Graph API using Google Apps Script?

I am using Facebook Graph API to create a Facebook ads campaign with Google Apps Script.
I need to upload an image to my Facebook ad account. I have already tried to use the image bytes as a Base64 UTF-8 string, but when I call the API I get:
Exception: Limit Exceeded: URLFetch URL Length.
Basically, the string is too long.
I am using the following code:
function uploadTest2() {
var image_id = 'blabla';
var image_blob = DriveApp.getFileById(image_id).getBlob();
var input = image_blob.getBytes();
var docImg = Utilities.base64Encode(input);
var account_id = '1111111111111';
var facebookUrl =
'https://graph.facebook.com/v7.0' +
'/act_' + account_id +
'/adimages?bytes=' + docImg +
'&access_token=' + TOKEN;
Logger.log(facebookUrl);
//var encodedFacebookUrl = encodeURI(facebookUrl);
var options = {
'method' : 'post'
};
var response = UrlFetchApp.fetch(facebookUrl, options);
var results = JSON.parse(response);
Logger.log(response);
}
The image does not exceed 5MB and I have already check the bytes string with an online decoder to verify it.
Do you have any idea on how to use the image URL directly in the post request?
The second version of the code:
function uploadTest2() {
var image_id = 'blabla';
var image_blob = DriveApp.getFileById(image_id).getBlob();
var input = image_blob.getBytes();
var docImg = Utilities.base64Encode(input);
var account_id = '1111111111111';
var facebookUrl =
'https://graph.facebook.com/v7.0' +
'/act_' + account_id +
// '/adimages?bytes=' + encodedImage +
// '&access_token=' + TOKEN;
'/adimages?access_token=' + TOKEN;
Logger.log(facebookUrl);
//var encodedFacebookUrl = encodeURI(facebookUrl);
var options = {
'method' : 'post',
'payload' : image_blob
};
var response = UrlFetchApp.fetch(facebookUrl, options);
var results = JSON.parse(response);
Logger.log(response);
}
Solution
In order to make a post request of an image with UrlFetchApp.fetch() you must provide the method, payload (i.e the body you want to POST) and sometimes the content type (if what we are passing is not a JavaScript object).
If you want to pass a base64Encode object obtained from a blob you should stringify this JSON object.
What the original poster was missing was to pass the payload and after my contribution and his work he finally solved the issue by editing the options variable such as:
var options = {
'method' : 'post',
'contentType': 'application/json',
'payload': JSON.stringify({"bytes": docImg,"name" : 'Test'})};
}
Documentation reference : Class UrlFetchApp

Kraken API private request authentication {"error":["EAPI:Invalid key"]} - Google Script

I have been trying to communicate with the private API on kraken. The error I get suggests {"error":["EAPI:Invalid key"]} that the encryption/decryption steps are correct. I have tried creating new keys, does not help. I'm wondering if the 'format' of the signature variable is wrong, even though correct in nature.
function balance () {
var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("API_read_only");
var key = sheet.getRange("B5").getValue()
var secret = sheet.getRange("B6").getValue()
// (API method, nonce, and POST data)
var path = "/0/private/TradeBalance"
var nonce = new Date () * 1000
var postdata = "nonce=" + nonce
//Algorithms
//Calculate the SHA256 of the nonce and the POST data
// using goolge script lib
// using more succint function from https://stackoverflow.com/questions/16216868/get-back-a-string-representation-from-computedigestalgorithm-value-byte
function SHA_256 (str) {
return Utilities.computeDigest(Utilities.DigestAlgorithm.SHA_256, str).reduce(function(str,chr){
chr = (chr < 0 ? chr + 256 : chr).toString(16);
return str + (chr.length==1?'0':'') + chr;
},'');
}
var api_sha256 = SHA_256(nonce + postdata)
//Decode the API secret (the private part of the API key) from base64 // need to stringyfy
var base64 = Utilities.base64Decode(secret)
var base64s = Utilities.newBlob(base64).getDataAsString()
//Calculate the HMAC of the URI path and the SHA256, using SHA512 as the HMAC hash and the decoded API secret as the HMAC key
var hamc512_uri = Utilities.computeHmacSha256Signature(path + api_sha256,base64s)
var hamc512_uris = Utilities.newBlob(hamc512_uri).getDataAsString()
//Encode the HMAC into base64
var signature = Utilities.base64Encode(hamc512_uris)
Logger.log(signature)
//An example of the algorithm using the variables shown above is as follows:
//Base64Encode(HMAC-SHA512 of ("/0/private/TradeBalance" + SHA256("1540973848000nonce=1540973848000&asset=xxbt")) using Base64Decode("FRs+gtq09rR7OFtKj9BGhyOGS3u5vtY/EdiIBO9kD8NFtRX7w7LeJDSrX6cq1D8zmQmGkWFjksuhBvKOAWJohQ==") as the HMAC key
//The result is the API-Sign value / signature.
// connect
var url = "https://api.kraken.com" + path;
var options = {
method: 'post',
headers: {
'API-Key': key,
'API-Sign': signature
},
payload: postdata
};
var response = UrlFetchApp.fetch (url, options);
json = response.getContentText ();
Logger.log(json)
}
While I cannot spot what's wrong with your code I faced the same problem as well (thinking I have everything correct but getting a EAPI:Invalid key) with different libraries.
The approach that helped me was:
Take some posted working solution, e.g. https://stackoverflow.com/a/43081507/672008 (in Java)
Check that it really works
Fix the nonce parameter to get a stable HMAC end results
Massage my code until I get then same intermediate & end results
In the end I was successful using this library: https://www.npmjs.com/package/jssha
The code:
import jssha from 'jssha';
const secret = '...';
const nonce = 1642383717038;
const message = '';
const path = '/0/private/Balance';
const data = 'nonce=' + nonce;
const dataHash = new jssha('SHA-256', 'TEXT');
dataHash.update(nonce + data + message);
let utf8Encode = new TextEncoder();
const hmacHash = new jssha('SHA-512', 'UINT8ARRAY', { hmacKey: { value: secret, format: 'B64' } });
hmacHash.update(utf8Encode.encode(path));
hmacHash.update(dataHash.getHash('UINT8ARRAY'));
console.log('hmac', hmacHash.getHash('B64'));

NodeJS equivalent of C# code for hmac-sha256 authorization

Im trying to convert the C# code found here:
AMX Authorization Header in order to connect to an external API. The C# code works when trying to connect to the external API but when I convert it to a nodeJS solution it doesnt work.
I dont have access to the external C# API so can't update that side but was hoping someone could look at this and see something Im missing or doing wrong:
My nodejs solution:
var request = require('request');
var uuid = require('node-uuid');
var CryptoJS = require('crypto-js');
var URL = "https://urltoexternalAPI.com";
var itemAPPId = "testAPPId";
var APIKey = "testAPIKey";
var requestUri = encodeURIComponent(URL.toLowerCase());
var requestHttpMethod = "GET";
var requestTimeStamp = Math.floor(new Date().getTime() / 1000).toString();
var nonce = uuid.v1().replace(/-/g, '');
//I excluded the content hashing part as the API Im hitting is a GET request with no body content
var signatureRawData = itemAPPId + requestHttpMethod + requestUri + requestTimeStamp + nonce;
var secretKeyByteArray = CryptoJS.enc.Base64.parse(APIKey);
var signature = CryptoJS.enc.Utf8.parse(signatureRawData);
var signatureBytes = CryptoJS.HmacSHA256(signature, secretKeyByteArray);
var requestSignatureBase64String = signatureBytes.toString(CryptoJS.enc.Base64);
request({
url: URL,
headers: {
'Authorization': "amx "+itemAPPId+":"+requestSignatureBase64String+":"+nonce+":"+requestTimeStamp
}
}, function (error, response, body) {
if (response.statusCode != 200) {
console.log("Fail");
} else {
console.log("Success");
}
});
I figured it out! If anyone ever comes across this issue they may find the below helpful:
the following C# code works a little different to nodeJS:
System.Web.HttpUtility.UrlEncode(request.RequestUri.AbsoluteUri.ToLower());
Initially I copied this functionality as is and wrote the nodejs equivalent as such:
var requestUri = encodeURIComponent(URL.toLowerCase());
The encoding of the URL in C# keeps everything in lowercase - for e.g: https:// becomes https%3a%2f%2f - whereas nodeJS uppercases its encoding characters - https%3A%2F%2F - this is what as causing the incorrect hashing.
The solution is to just move the lowercase function to after the encoding has been done on the URL. Like so:
var requestUri = encodeURIComponent(URL).toLowerCase();
Seems rather simple but when trying to replicate the C# solution you may not pick up that the two URL encoders work differently.
Final solution: (updated to crypto thanks to Yoryo)
const fetch = require("node-fetch");
const uuid = require("uuid");
const crypto = require('crypto');
var URL = "https://urltoapi.com";
var itemAPPId = config.itemAPPId;
var APIKey = config.itemAPIKey;
var requestUri = encodeURIComponent(URL).toLowerCase();
var requestHttpMethod = "GET"; //should be dynamic
var requestTimeStamp = Math.floor(new Date().getTime() / 1000).toString();
var nonce = uuid.v1().replace(/-/g, '');
var signatureRawData = itemAPPId + requestHttpMethod + requestUri + requestTimeStamp + nonce;
var key = Buffer.from(APIKey, 'base64');
var requestSignatureBase64String = crypto.createHmac('sha256', key).update(signatureRawData, 'utf8').digest('base64');
const hitExternalAPI = async url => {
try {
const res = await fetch(url, { method: 'GET', headers: { "Authorization": "amx "+itemAPPId+":"+requestSignatureBase64String+":"+nonce+":"+requestTimeStamp } })
.then(res => {
console.log(res.ok);
});
} catch (error) {
console.log("Error",error);
}
};
hitExternalAPI(URL);

CryptoJs is not decrypting URL on my NodeJS server

I am forwarding API calls from my frontend to my backend. I encrypt the API calls using CryptoJS.AES using the passphrase 'somekey'.
My relevant client code is...
var host = 'http://localhost:3000'
$('.send-button').click(function(){
var request = $('.request-input').val();
var encryptedRequest = CryptoJS.AES.encrypt(request, 'somekey');
console.log(encryptedRequest.toString())
var decryptedRequest = CryptoJS.AES.decrypt(encryptedRequest, 'somekey');
console.log('Decrypted Request: ' + decryptedRequest.toString());
handleRequest(encryptedRequest.toString());
});
var handleRequest = function(request){
$.ajax({
type: "GET",
url: host + '/requests?call=' + request,
success: function(data) {
var rawJSON = JSON.stringify(data, null, 2);
editor.setValue(rawJSON);
},
dataType: 'json'
});
}
relevant server side code is...
var port = 3000;
var serverUrl = "127.0.0.1";
var http = require("http");
var path = require("path");
var fs = require("fs");
var express = require("express");
var CryptoJs = require("crypto-js");
var app = express();
app.get('/requests', function(req, res) {
console.log('REQUEST: ' + req);
var call = req.query.call;
console.log(call)
console.log("To send: " + CryptoJs.AES.decrypt(call, 'somekey'));
});
The problem I keep getting is that it that when I decrypt it it either doesn't get the original URL and instead returns a bunch of jibberish. An example of this is...
Encryption: U2FsdGVkX1/NRbZkyP60pPu3Cb9IcQ4b9n4zJkExp2LNR3O1EdEpqHLNACnYuatN
Decryption: 68747470733a2f2f6e6577736170692e6f72672f76312f61727469636c6573
OR... It just returns nothing and appears blank.
Ideally I would like something like this.
Encryption: U2FsdGVkX1/NRbZkyP60pPu3Cb9IcQ4b9n4zJkExp2LNR3O1EdEpqHLNACnYuatN
Decryption: https://newsapi.org/v1/articles
Can anyone see what I am dong wrong?
Here is a working jsfiddle:
https://jsfiddle.net/5Lr6z4zp/1/
The encryption results in a Base64 string, while the decrypted string is Hex. To get back the “Message” you need to convert that to Utf8: decryptedRequest.toString(CryptoJS.enc.Utf8)
Here is the relevant part of the code that works:
var request = "testing decryption";
var encryptedRequest = CryptoJS.AES.encrypt(request, 'somekey');
console.log(encryptedRequest)
var decryptedRequest = CryptoJS.AES.decrypt(encryptedRequest, 'somekey');
var decryptedMessage = decryptedRequest.toString(CryptoJS.enc.Utf8)
console.log('Decrypted Request: ' + decryptedMessage);
Here is a link for a resources that explains the encryption/decryption in more detail:
http://www.davidebarranca.com/2012/10/crypto-js-tutorial-cryptography-for-dummies/

Convert Node.JS code snippet to Javascript (Google Apps Script)

I would like to convert the following Node.JS code snippet to JavaScript in order to run it in Google Apps Script:
From: Node.JS
function getMessageSignature(path, request, nonce) {
var message = querystring.stringify(request);
var secret = new Buffer(config.secret, 'base64');
var hash = new crypto.createHash('sha256');
var hmac = new crypto.createHmac('sha512', secret);
var hash_digest = hash.update(nonce + message).digest('binary');
var hmac_digest = hmac.update(path + hash_digest, 'binary').digest('base64');
return hmac_digest;
}
This is the code I have tried so far (and many variations of it):
To: JavaScript / Google Apps Script
function getMessageSignature(url, request, nonce) {
// Message signature using HMAC-SHA512 of (URI path + SHA256(nonce + POST data))
//and base64 decoded secret API key
const secretApiKey = 'wdwdKswdKKewe23edeYIvL/GsltsGWbuBXnarcxZfu/9PjFbXl5npg==';
var secretApiKeyBytes = Utilities.base64Decode(secretApiKey);
var blob = Utilities.newBlob(secretApiKeyBytes);
var secretApiKeyString = blob.getDataAsString(); // POTENTIAL ERROR HERE?
var json = Utilities.jsonStringify(request);
var hash_digest = Utilities.computeDigest(Utilities.DigestAlgorithm.SHA_256,
nonce + json);
var hmac_digest = Utilities.computeHmacSignature(Utilities.MacAlgorithm.HMAC_SHA_512,
url + hash_digest, secretApiKeyString); // POTENTIAL ERROR HERE?
var base64 = Utilities.base64Encode(hmac_digest);
return base64;
}
When sending the signature as part of my request to the server, I always get the error message from the server: Invalid Key.
BTW: This is the API which I would like to use in JavaScript: Kraken API
I would appreciate any hint or suggestions very much!!
Solution:
Use jsSHA (https://github.com/Caligatio/jsSHA/) rather than Google App Script's functions. Create a new "jsSHA.gs" code file in Google App Script and copy/past in all the jsSHA optimised .js files from github.
function getKrakenSignature (path, postdata, nonce) {
var sha256obj = new jsSHA ("SHA-256", "BYTES");
sha256obj.update (nonce + postdata);
var hash_digest = sha256obj.getHash ("BYTES");
var sha512obj = new jsSHA ("SHA-512", "BYTES");
sha512obj.setHMACKey (api_key_private, "B64");
sha512obj.update (path);
sha512obj.update (hash_digest);
return sha512obj.getHMAC ("B64");
}
function getKrakenBalance () {
var path = "/0/private/Balance";
var nonce = new Date () * 1000;
var postdata = "nonce=" + nonce;
var signature = getKrakenSignature (path, postdata, nonce);
var url = api_url + path;
var options = {
method: 'post',
headers: {
'API-Key': api_key_public,
'API-Sign': signature
},
payload: postdata
};
var response = UrlFetchApp.fetch (url, options);
// ERROR handling
return response.getContentText ();
}
One problem is that querystring.stringify is not the same as Utilities.jsonStringify (which, FYI, is deprecated in favor of JSON.stringify).
I believe that this will be equivalent:
function queryStringify(obj) {
var params = [];
for(var key in obj) {
if(Object.hasOwnProperty(key)) {
if(typeof key === 'string') {
params.push([key, obj[key]]);
} else {
obj[key].forEach(function(val) {
params.push([key, val]);
});
}
}
}
return params.map(function(param) {
return encodeURIComponent(param[0]) + '=' + encodeURIComponent(param[1]);
}).join('&');
}
Though I am not sure if that is the reason you are seeing your error.
I noticed this nodejs to GS converter: https://www.npmjs.com/package/codegs
Haven't got the chance to use it, but it claims to handle 'require'-statements.

Categories

Resources