Trying to send a file message to bale.ai bot. Upload seems working correctly but when it reach send function the connection will be reseted. What is the problem?
let ddd = fs.readFileSync(__dirname + '/a.html')
bot.UploadFile(ddd,'file').then(response => {
let fileId = response.fileId
let fileAccessHash = response.accessHash
let fileŁ°Version = response.version
const stats = fs.statSync(__dirname + '/a.html')
var file = new SDK.FileMessage(fileId, fileAccessHash, 'telename', stats.size, 'text/html', 'see')
bot.send(file, responder.peer)
fileId and accessHash must be string, replace this line
var file = new SDK.FileMessage(fileId.toString(), fileAccessHash.toString(), 'telename', stats.size, 'text/html', 'see')
with yours.
Related
I am a newer Apps Scripts user who has been stuck on this problem for some time. I am trying to connect my company's reporting feature to a Google Sheet so I can create reporting dashboards for our users.
I have a .jsNode code snippet which I am able to successfully run outside of the Apps Scripts editor, but I am having issues translating it to Apps Scripts.
My goal is to be able to generate an Authentication Token which will be used in a header within a POST request. I will then use this to get a specific URL that I can pull data from (it will be a .csv file. I already feel I can accomplish this using another script)
Below is the .NodeJS code snippet:
const crypto = require('crypto');
module.exports.init = function () {
let prefix = 'abc-admin-v1'
let businessId = 'XXXX'
let publicAppKeyId = 'XXXX'
let secretKey = 'XXXX'
let unixTimestamp = Math.floor(Date.now() / 1000)
let payload = `${prefix}${businessId}${unixTimestamp}`
let rawKey = Buffer.from(secretKey, 'base64')
let signature = crypto.createHmac('sha256', rawKey).update(payload, 'utf8').digest('base64')
let token = `${signature}${payload}`
let httpBasicPayload = `${publicAppKeyId}:${token}`
let httpBasicCredentials = Buffer.from(httpBasicPayload, 'utf8').toString('base64')
console.log(httpBasicCredentials);
};
Below will be what I have in Apps Scripts:
function apiInfo() {
var secret = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
var apiKey = "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX";
var locationID = "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX";
var prefix = "abc-admin-v1";
var timeStamp = Math.round((new Date()).getTime() / 1000);
var timeStampReal = JSON.stringify(timeStamp);
var tokenPayload = prefix + businessID + timeStampReal;
var enCodeTokenPayload = Utilities.base64Encode(tokenPayload);
var deCodeTokenPayload = Utilities.base64Decode(enCodeTokenPayload);
var tokenPayloadReal = JSON.stringify(tokenPayload);
var rawKey = Utilities.base64Decode(secret);
var rawMac = Utilities.computeHmacSha256Signature(tokenPayloadReal, rawKey);
var signature = Utilities.base64Encode(rawMac);
var token = signature + tokenPayload;
var httpBasicPayload = apiKey + ":" + token;
var httpBasicCredentials = Utilities.base64Encode(httpBasicPayload);
When testing using the current GAS code, it produces an invalid Auth Token.
When I run the Node.js version outside of GAS, it produces a valid Auth Token. I am looking to find out what is currently wrong with my code that is producing an invalid auth token. I would like to keep the project within GAS if possible.
I believe your goal is as follows.
You want to convert your showing Node.js script to Google Apps Script. Namely, you want to retrieve the same values of httpBasicCredentials between your Node.js script and Google Apps Script.
const crypto = require('crypto');
module.exports.init = function () {
let prefix = 'abc-admin-v1'
let businessId = 'XXXX'
let publicAppKeyId = 'XXXX'
let secretKey = 'XXXX'
let unixTimestamp = Math.floor(Date.now() / 1000)
let payload = `${prefix}${businessId}${unixTimestamp}`
let rawKey = Buffer.from(secretKey, 'base64')
let signature = crypto.createHmac('sha256', rawKey).update(payload, 'utf8').digest('base64')
let token = `${signature}${payload}`
let httpBasicPayload = `${publicAppKeyId}:${token}`
let httpBasicCredentials = Buffer.from(httpBasicPayload, 'utf8').toString('base64')
console.log(httpBasicCredentials);
};
When I saw your showing Google Apps Script, unfortunately, there are several undeclared variable and unused variables. By this, in this answer, I would like to propose to directly converting your showing Node.js to Google Apps Script.
Sample script:
function myFunction() {
let prefix = 'abc-admin-v1'
let businessId = 'XXXX'
let publicAppKeyId = 'XXXX'
let secretKey = 'XXXX'
let unixTimestamp = Math.floor(Date.now() / 1000);
let payload = `${prefix}${businessId}${unixTimestamp}`;
let payloadBytes = Utilities.newBlob(payload).getBytes();
let rawKey = Utilities.base64Decode(secretKey);
let signature = Utilities.base64Encode(Utilities.computeHmacSha256Signature(payloadBytes, rawKey));
let token = `${signature}${payload}`;
let httpBasicPayload = `${publicAppKeyId}:${token}`;
let httpBasicCredentials = Utilities.base64Encode(httpBasicPayload);
console.log(httpBasicCredentials);
}
Testing:
In the above scripts, when the value of unixTimestamp is 1661403828, both your Node.js and my sample Google Apps Script are the same values as follows.
WFhYWDpGYXBwRk9kaFoxdDVQNGVkV2JJbFIvR1RiMkEyZ0hwYThld05BYjVDVkxnPWFiYy1hZG1pbi12MVhYWFgxNjYxNDAzODI4
Note:
From your question, in this answer, your Node.js is converted to Google Apps Script. Please be careful about this.
References:
base64Encode(data)
computeHmacSha256Signature(value, key)
I am trying to send 6 x Excel Sheets as Attachment from 1 Google Sheet as Attachment, sometimes this code run's perfectly but sometime it gives the error.
The Original Code
///*** SEND 6 X ATTACHMENTS IN 1 EMAIL FROM GOOGLE SHEET USING APP SCRIPT ***///
function sendExcelAttachmentsInOneEmail() {
var url = "https://docs.google.com/spreadsheets/d/"+SpreadsheetApp.getActiveSpreadsheet().getId()+"/export"+"?format=xlsx&"+"gid="+SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Sheet1").getSheetId();
var url1 = "https://docs.google.com/spreadsheets/d/"+SpreadsheetApp.getActiveSpreadsheet().getId()+"/export"+"?format=xlsx&"+"gid="+SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Sheet2").getSheetId();
var url2 = "https://docs.google.com/spreadsheets/d/"+SpreadsheetApp.getActiveSpreadsheet().getId()+"/export"+"?format=xlsx&"+"gid="+SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Sheet3").getSheetId();
var url3 = "https://docs.google.com/spreadsheets/d/"+SpreadsheetApp.getActiveSpreadsheet().getId()+"/export"+"?format=xlsx&"+"gid="+SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Sheet4").getSheetId();
var url4 = "https://docs.google.com/spreadsheets/d/"+SpreadsheetApp.getActiveSpreadsheet().getId()+"/export"+"?format=xlsx&"+"gid="+SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Sheet5").getSheetId();
var url5 = "https://docs.google.com/spreadsheets/d/"+SpreadsheetApp.getActiveSpreadsheet().getId()+"/export"+"?format=xlsx&"+"gid="+SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Sheet6").getSheetId();
var ss3 = SpreadsheetApp.getActiveSpreadsheet();
var sheet3 = ss3.getSheetByName("Sheet7");
var value4 = sheet3.getRange("J1").getValue();
var params = {method:"GET",headers:{"authorization":"Bearer "+ ScriptApp.getOAuthToken()}};
var blob = UrlFetchApp.fetch(url, params).getBlob().setName("Sheet1 XYZ Reports.xlsx");
var blob1 = UrlFetchApp.fetch(url1, params).getBlob().setName("Sheet2 TXT Data.xlsx");
var blob2 = UrlFetchApp.fetch(url2, params).getBlob().setName("Sheet3 RAW FILES.xlsx");
var blob3 = UrlFetchApp.fetch(url3, params).getBlob().setName("Sheet4 SYS DATA.xlsx");
var blob4 = UrlFetchApp.fetch(url4, params).getBlob().setName("Sheet5 REPORTED ISSUES.xlsx");
var blob5 = UrlFetchApp.fetch(url5, params).getBlob().setName("Sheet6 FIXED ISSUES.xlsx");
var message = {
to: "email#domain.com",
cc: "email#domain.com",
subject: "REPORTS - "+value4,
body: "Hi Team,\n\nPlease find attached Reprots.\n\nBest Regards!",
name: "",
attachments: [blob, blob1, blob2, blob3, blob4, blob5]
}
MailApp.sendEmail(message);
}
Error Message from App Script
9:05:45 PM Notice Execution started
9:05:49 PM Error Exception: Request failed for https://docs.google.com returned code 429. Truncated server response: <!DOCTYPE html><html lang="en"><head><meta name="description" content="Web word processing, presentations and spreadsheets"><meta name="viewport" c... (use muteHttpExceptions option to examine full response)
sendExcelAttachmentsInOneEmail # Code.gs:44
I have made it work and also did an overhaul to the script due to personal reasons (I don't like repetitive lines of code). See the working script below.
Script:
function sendExcelAttachmentsInOneEmail() {
var sheets = ['Sheet1', 'Sheet2', 'Sheet3', 'Sheet4', 'Sheet5', 'Sheet6'];
var spreadSheet = SpreadsheetApp.getActiveSpreadsheet();
var spreadSheetId = spreadSheet.getId();
var urls = sheets.map(sheet => {
var sheetId = spreadSheet.getSheetByName(sheet).getSheetId();
// Used this alternative url since I'm getting the error below. This other url has less traffic issues during testing:
// "This file might be unavailable right now due to heavy traffic. Try again."
return `https://docs.google.com/feeds/download/spreadsheets/Export?key=${spreadSheetId}&gid=${sheetId}&exportFormat=xlsx`;
});
var reportName = spreadSheet.getSheetByName('Sheet7').getRange(1, 10).getValue();
var params = {
method: 'GET',
headers: {
'Authorization': 'Bearer ' + ScriptApp.getOAuthToken()
},
// Add mute http exceptions to proceed
muteHttpExceptions: true
};
var fileNames = ['Sheet1 XYZ Reports.xlsx',
'Sheet2 TXT Data.xlsx',
'Sheet3 RAW FILES.xlsx',
'Sheet4 SYS DATA.xlsx',
'Sheet5 REPORTED ISSUES.xlsx',
'Sheet6 FIXED ISSUES.xlsx'];
var blobs = urls.map((url, index) => {
// Added an interval due to heavy traffic error. Increase interval if needed.
Utilities.sleep(1000);
return UrlFetchApp.fetch(url, params).getBlob().setName(fileNames[index]);
});
var message = {
to: 'user#domain.com',
subject: 'REPORTS - ' + reportName,
body: "Hi Team,\n\nPlease find attached Reports.\n\nBest Regards!",
attachments: blobs
}
MailApp.sendEmail(message);
}
Output:
Notes:
Important bits here are the following:
muteHttpExceptions
The alternative url for less traffic issues
Utilities.sleep(1000)
I'm trying to make a request to the Amazon Selling Partner API (node.js/Lambda) but I currently always get a 403 error back. I have plugged the same credentials and access token into Postman and the request works fine. I believe that there must be an error when I'm calculating the signature for the request, but I can't see anything wrong.
I'm calculating the signature as follows:
function constructCanonicalRequest(accessToken, dateTime) {
let canonical = [];
canonical.push('GET');
canonical.push('/fba/outbound/2020-07-01/fulfillmentOrders/FBATestOrder-1');
canonical.push('');
canonical.push('host:' + 'sandbox.sellingpartnerapi-na.amazon.com');
canonical.push('x-amz-access-token:' + accessToken);
canonical.push('x-amz-date:' + dateTime);
canonical.push('');
canonical.push('host;x-amz-access-token;x-amz-date');
canonical.push(crypto.SHA256(''));
let canonicalRequest = canonical.join('\n');
let canonicalRequestHash = crypto.SHA256(canonicalRequest);
return canonicalRequestHash
};
function constructStringToSign(dateTime, date, canonicalRequestHash) {
let stringToSign = [];
stringToSign.push('AWS4-HMAC-SHA256')
stringToSign.push(dateTime);
stringToSign.push(date + '/' + 'us-east-1' + '/' + 'execute-api' + '/aws4_request');
stringToSign.push(canonicalRequestHash);
return stringToSign.join('\n');
};
function constructSignature(date, iamSecret, stringToSign) {
let kDate = crypto.HmacSHA256(date, 'AWS4' + iamSecret);
let kRegion = crypto.HmacSHA256('us-east-1', kDate);
let kService = crypto.HmacSHA256('execute-api', kRegion);
let kSigning = crypto.HmacSHA256('aws4_request', kService);
let signature = crypto.HmacSHA256(stringToSign, kSigning).toString(crypto.enc.Hex);
return signature
};
The rest of the function is:
let dateTimeISO = new Date().toISOString();
let dateTime = dateTimeISO.replace(/(\.\d{3})|\W/g,'');
let date = dateTime.split('T')[0];
let canonicalRequestHash = constructCanonicalRequest(accessToken, dateTimeISO);
let stringToSign = constructStringToSign(dateTime, date, canonicalRequestHash);
let signature = constructSignature(date, iamSecret, stringToSign);
let authHeader = 'AWS4-HMAC-SHA256 Credential=' + iamId + '/' + date + '/' + 'us-east-1' + '/execute-api/aws4_request, SignedHeaders=host;x-amz-access-token;x-amz-date, Signature=' + signature
console.log(authHeader);
let amazonUrl = "https://sandbox.sellingpartnerapi-na.amazon.com/fba/outbound/2020-07-01/fulfillmentOrders/FBATestOrder-1";
const amazonResponse = await fetch(amazonUrl, {
method: 'get',
headers: {
'Authorization':authHeader,
'Content-Type':'application/json; charset=utf-8',
'host':'sandbox.sellingpartnerapi-na.amazon.com',
'x-amz-access-token':accessToken,
'user-agent': 'My Selling Tool/2.0 (Language=JS;Platform=Node)',
'x-amz-date':dateTime,
}
});
I have also tried using multiple difference crypto libraries to see if the HMAC creation is the problem, but this hasn't fixed anything.
I have my access working in C#. There is a Java library available on GitHub:
https://github.com/amzn/selling-partner-api-docs/blob/main/guides/en-US/developer-guide/SellingPartnerApiDeveloperGuide.md
I just followed the instructions there, though there is a deficiency in the C# lib about assume role, that is in the java lib.
I am creating a Video Chat App with WerbRTC + NodeJS + Socket.io but I have problems to recover the video and show in a video HTML element.
Client 1, I capture the stream blob with next code
this.mediaRecorder = new MediaRecorder(this.stream, options);
this.mediaRecorder.ondataavailable = dataAvailable.bind(this);
this.mediaRecorder.start(10);
function dataAvailable(e){
socket.emit('streaming', e.data);
};
Server I just receive the bytes and resend to the client2
this.streaming = function(data){
for (var key in clients) {
if(key != data.clientID){
var client = clients[key];
client.emit('streaming', data);
};
};
}.bind(this); socket.on('streaming', this.streaming);
All above is working, but my question is when I receive the ArrayBuffer how I process it to display the streaming again in a video tag elements, I try with the next code, but not work.
Client 2
this.type = 'video/webm;codecs=vp9';
this.blob = new Blob([], { type:this.type});
this.receiveStream = function(data){
var stream = data.stream;
if(stream.byteLength <= 0) return;
this.blob = new Blob([this.blob, new Uint8Array(stream)], { type:this.type});
this.nodes.video.src = URL.createObjectURL(this.blob);
}
Thank you....
I am trying to call a RestLet webservice/URL from another SuiteScript. As i understand I need to use the http/https module to do so. But I am not able to find some example or steps to do so.
Planning to use this code in SS2.0-
var response = http.post({
url: 'https://rest.na1.netsuite.com/app/site/hosting/restlet.nl?script=601&deploy=1',
body: myDataObj, // json object
headers: headerObj // json obj
});
The below code works for me.
var nameValue = "arin";
var myDataObj = {
"name" : nameValue
};
var myRequest = {};
myRequest.headers = {};
myRequest.headers["Authorization"] = 'NLAuth nlauth_account=TSTDRV158xxxx,nlauth_email=XXXX,nlauth_signature=XXXX,nlauth_role=3';
myRequest.headers["Content-Type"] = 'application/json';
myRequest.headers["Accept"] = '*/*';
myRequest.url = 'https://rest.na1.netsuite.com/app/site/hosting/restlet.nl?script=601&deploy=1'; // RESTlet
// URL
myRequest.method = "POST";
myRequest.body = JSON.stringify(myDataObj);
// myRequest.body = myDataObj;
var myResponse = https.post(myRequest);
And reading the response data for JSON return ...
log.debug("Resonse", myResponse.body);
log.debug("Resonse", myResponse.code);
var data = myResponse.body;
var retObj = JSON.parse(data);
log.debug("Resonse Ret city - ", retObj.city);
Here's a basic example of how to do it:
var myRequest = {};
myRequest.headers = {};
myRequest.headers["Authorization"] = 'NLAuth nlauth_account=TSTDRVXXXXX, nlauth_email=xxx#xxx.com, nlauth_signature=XXXXXXX, nlauth_role=3';
myRequest.headers["contentType"] = 'application/json';
myRequest.url = 'https://XXXXXXXXX'; //RESTlet URL
myRequest.body = myDataObj;
var myResponse = https.post(myRequest);
Be careful exposing this on clientside scripts. You don't want to expose your credentials.