Not able to receive an attachment from Skype in BotFramework - node.js

On BotFramework (NodeJS), I was trying to replicate the demo available at https://learn.microsoft.com/en-us/bot-framework/nodejs/bot-builder-nodejs-send-receive-attachments . It actually works well.
Code in case ms article change:
// Create your bot with a function to receive messages from the user
var bot = new builder.UniversalBot(connector, function (session) {
var msg = session.message;
if (msg.attachments && msg.attachments.length > 0) {
// Echo back attachment
var attachment = msg.attachments[0];
session.send({
text: "You sent:",
attachments: [
{
contentType: attachment.contentType,
contentUrl: attachment.contentUrl,
name: attachment.name
}
]
});
} else {
// Echo back users text
session.send("You said: %s", session.message.text);
}
});
However, the problem I am facing is that when I do a call from Skype (Normal), I receive an error message:
2017-12-07T02:16:15.815Z Error: POST to 'https://smba.trafficmanager.net/apis/v3/conversations/<My Conversation>/activities' failed: [400] Bad Request
at Request._callback (/app/node_modules/botbuilder/lib/bots/ChatConnector.js:545:46)
at Request.self.callback (/app/node_modules/request/request.js:186:22)
at emitTwo (events.js:126:13)
at Request.emit (events.js:214:7)
at Request.<anonymous> (/app/node_modules/request/request.js:1163:10)
at emitOne (events.js:116:13)
at Request.emit (events.js:211:7)
at IncomingMessage.<anonymous> (/app/node_modules/request/request.js:1085:12)
at Object.onceWrapper (events.js:313:30)
at emitNone (events.js:111:20)
Any ideas?
[Update: It happens only when I create the attachment response. So I expect that's where I have an issue]

Actually the code on the MS Website is not up-to-date (in a way).
If I follow the code visible at : https://github.com/Microsoft/BotBuilder-Samples/tree/master/Node/core-ReceiveAttachment
By example, I can receive the attachment and save it somewhere on a public folder. Once completed, then I can send back the "public" URL as attachment and then it works.

Related

Duplicate Content-Length with Axios running in NodeJS/JEST

I face really weird problem with Axios / nanoexpress. I started to write JEST test and copied working piece of code from Vuex that calls my backend. This code works reliably in Vue but here it fails with a network error. The Axios version is the same on both SPA and JEST test.
JEST:
let response = await axios.get(`${API}/users/1234`, getAuthHeader());
function getAuthHeader() {
const config = { headers: { } };
config.headers.Authorization = "bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOiIxZTQwdjBiMWo1Iiwibmlja25hbWUiOiJsaXRlcmFrbCIsInB3ZFRpbWVzdGFtcCI6IjIwMjAtMDMtMjJUMTE6MTA6NDkuNDg2WiIsInJvbGVzIjpbImFkbWluOnBvbGwiXSwiaWF0IjoxNTg2NjkwNzc2LCJleHAiOjE1ODkzNjkxNzZ9.N5MfpZ9i9Sjv-izdYItR4gXCmzVkqkuVcVSEL_6Q89c";
return config;
}
When I remove the config with Authorization header, the code works well:
let response = await axios.get(`${API}/users/1234`, getAuthHeader());
This is the error:
Network Error
at createError (node_modules/axios/lib/core/createError.js:16:15)
at XMLHttpRequest.handleError (node_modules/axios/lib/adapters/xhr.js:83:14)
at XMLHttpRequest.<anonymous> (node_modules/jsdom/lib/jsdom/living/helpers/create-event-accessor.js:33:32)
at innerInvokeEventListeners (node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:316:27)
at invokeEventListeners (node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:267:3)
at XMLHttpRequestEventTargetImpl._dispatch (node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:214:9)
at fireAnEvent (node_modules/jsdom/lib/jsdom/living/helpers/events.js:17:36)
at requestErrorSteps (node_modules/jsdom/lib/jsdom/living/xhr-utils.js:121:3)
at Object.dispatchError (node_modules/jsdom/lib/jsdom/living/xhr-utils.js:51:3)
at EventEmitter.<anonymous> (node_modules/jsdom/lib/jsdom/living/xmlhttprequest.js:675:20)
at Request.<anonymous> (node_modules/jsdom/lib/jsdom/living/xhr-utils.js:384:47)
at Request.onRequestError (node_modules/request/request.js:877:8)
console.error node_modules/jsdom/lib/jsdom/virtual-console.js:29
Error: Error: Parse Error: Duplicate Content-Length
at Object.dispatchError (C:\Users\leos\WebstormProjects\nano-options\node_modules\jsdom\lib\jsdom\living\xhr-utils.js:54:19)
at EventEmitter.<anonymous> (C:\Users\leos\WebstormProjects\nano-options\node_modules\jsdom\lib\jsdom\living\xmlhttprequest.js:675:20)
at EventEmitter.emit (events.js:327:22)
at Request.<anonymous> (C:\Users\leos\WebstormProjects\nano-options\node_modules\jsdom\lib\jsdom\living\xhr-utils.js:384:47)
at Request.emit (events.js:315:20)
at Request.onRequestError (C:\Users\leos\WebstormProjects\nano-options\node_modules\request\request.js:877:8)
at ClientRequest.emit (events.js:315:20)
at Socket.socketOnData (_http_client.js:486:9)
at Socket.emit (events.js:315:20)
at addChunk (_stream_readable.js:297:12) undefined
The service is nothing fancy and it is never called when Authorization header is present and it is called when the Authorization header is missing.
app.get('/v1/users/:userId', async (req, res) => {
console.log("getUser handler starts");
const response = {};
res.send(response);
return res;
});
I have spent several hours trying to see the raw network communication but failed. It must be something with Axios because I can run successfuly exactly the same request with the Authorization header from Postman.
Update:
it seems to be related to NodeJS version. I submitted an issue: https://github.com/axios/axios/issues/2889
Update 2:
I switched from Axios to Got and the test is working properly. https://github.com/literakl/mezinamiridici/commit/e667c5661429fc8cba273716dfced2244e211abf

ERROR event: Not Found; when triggering event from another event : probot app built in nodejs

I am building a GitHub app in probot and nodejs and trying to update the PR whenever a pull_request.synchronize event occurs. I know that doesn't make much sense, but the point is I want to be able to update the PR upon the occurrence of a certain event.
app.on('pull_request.synchronize', async context => {
console.log('---------------------- on pull_request.synchronize, body of PR : ', context.payload.pull_request)
console.log('State of PR after pull_request.synchronize event :---------------', context.payload.pull_request.state)
await context.github.pulls.update({
owner:context.payload.repository.owner,
repo :context.payload.repository.name,
pull_number :context.payload.pull_request.number,
title:'updated Pull Request Title: Success',
body:'updated Pull Request Body: Success',
})
})
I get below error every time :
ERROR event: Not Found (id=ssjsk-dd-sdfsdfs-fsfs-fsfsfsffsd)
HttpError: Not Found
at response.text.then.message (C:\GitWorkspace\user\GitHubApps\github-app-name\node_modules\#octokit\request\dist-node\index.js:66:23)
at process._tickCallback (internal/process/next_tick.js:68:7)
--
event: {
"event": "pull_request.synchronize",
"id": "2332-3131-131-31231313-1313232144142",
"installation": 3352243,
"repository": "user/Demo-Repo"
}
06:24:58.460Z ERROR probot: Not Found
HttpError: Not Found
at response.text.then.message (C:\GitWorkspace\user\GitHubApps\github-app-name\node_modules\#octokit\request\dist-node\index.js:66:23)
at process._tickCallback (internal/process/next_tick.js:68:7)
06:24:58.472Z INFO http: POST / 500 - 519.93 ms (id=3424234-43242-42423478a-4242-42342342)
06:24:58.476Z ERROR probot: Internal Server Error
Error: Internal Server Error
at Request.callback (C:\GitWorkspace\user\GitHubApps\github-app-name\node_modules\superagent\lib\node\index.js:706:15)
at IncomingMessage.parser (C:\GitWorkspace\user\GitHubApps\github-app-name\node_modules\superagent\lib\node\index.js:916:18)
at IncomingMessage.emit (events.js:203:15)
at IncomingMessage.EventEmitter.emit (domain.js:448:20)
at endReadableNT (_stream_readable.js:1129:12)
at process._tickCallback (internal/process/next_tick.js:63:19)
Why is it unable to get the detail out of context, when in fact the context does get printed out by my console statement and contains the pull_request details.
I am just a beginner in both probot and nodejs so I am not sure if this has anything to to do with the syntax.
The problem is that context.payload.repository.owner is an object, compare the example payload at https://developer.github.com/v3/activity/events/types/#webhook-payload-example-28
Try to replace it with context.payload.repository.owner.login.
Probot also provides a convenience method which returns and { owner, repo } object based on the context, and you can pass extra parameters to it
Try the following
await context.github.pulls.update(context.repo({
pull_number: context.payload.pull_request.number,
title:'updated Pull Request Title: Success',
body:'updated Pull Request Body: Success',
}))

nodejs (twit) how do you follow a users LIVE twitter stream

I am trying to get twit (https://www.npmjs.com/package/twit) to stream live tweets from specific twitter users.
The code I have is
var stream = T.stream('statuses/filter', { follow: ['nodejs'] })
stream.on('tweet', function (tweet) {
console.log(tweet.text)
})
but it gives the following error
Error: Bad Twitter streaming request: 406
at Object.exports.makeTwitError (/Users/simoncarr/dev/node/nodeletetweet/scripts/get_mp_data/node_modules/twit/lib/helpers.js:74:13)
at Request.<anonymous> (/Users/simoncarr/dev/node/nodeletetweet/scripts/get_mp_data/node_modules/twit/lib/streaming-api-connection.js:96:29)
at Request.emit (events.js:187:15)
at Gunzip.<anonymous> (/Users/simoncarr/dev/node/nodeletetweet/scripts/get_mp_data/node_modules/request/request.js:1083:12)
at Object.onceWrapper (events.js:273:13)
at Gunzip.emit (events.js:187:15)
at endReadableNT (_stream_readable.js:1094:12)
at process._tickCallback (internal/process/next_tick.js:63:19)
Emitted 'error' event at:
at Request.<anonymous> (/Users/simoncarr/dev/node/nodeletetweet/scripts/get_mp_data/node_modules/twit/lib/streaming-api-connection.js:99:14)
at Request.emit (events.js:187:15)
[... lines matching original stack trace ...]
at process._tickCallback (internal/process/next_tick.js:63:19)
simply tracking words in a tweet works just fine, for instance the following code works OK.
var stream = T.stream('statuses/filter', { track: ['apples'] })
stream.on('tweet', function (tweet) {
console.log(tweet.text)
})
The twitter documentation suggests that I should be able to simply replace track with follow.
https://developer.twitter.com/en/docs/tweets/filter-realtime/api-reference/post-statuses-filter.html
You need to use the numeric user ID, not the screen name, in the follow parameter. You can use the users/show endpoint to find the user ID for a given screen name.

Node server is getting down with error buffer.js:488 throw new Error('toString failed');

We have an app build on nodejs (Server A), which is fetching data from another nodejs app(Server B) using REST API's.
Similarly for downloading files Server A make request on Server B and Server B fetches files from AWS S3 and pipes the data back to server A.
This system works perfectly and we are able to download files upto 1GB.
Issue is sometimes Server A crashes with below error:
buffer.js:488
throw new Error('toString failed');
^
Error: toString failed
at Buffer.toString (buffer.js:488:11)
at Request.<anonymous> (/var/www/sky/portal/node_modules/request/request.js:1145:39)
at emitOne (events.js:95:20)
at Request.emit (events.js:182:7)
at IncomingMessage.<anonymous> (/var/www/sky/portal/node_modules/request/request.js:1091:12)
at IncomingMessage.g (events.js:273:16)
at emitNone (events.js:85:20)
at IncomingMessage.emit (events.js:179:7)
at endReadableNT (_stream_readable.js:913:12)
at _combinedTickCallback (internal/process/next_tick.js:74:11)
at process._tickCallback (internal/process/next_tick.js:98:9)
Server A is calling server B using below code:
exports.downloadAsset = function(req, res, assetUrl, cb) {
res.cookie('fileDownload', 'true');
request(
config.api.baseUrl + assetUrl
,
function(error, response, body) {
}
).pipe(res);
}
We are not sure from where app is getting crashed.
Please suggest.
The Solution I used to sort above issue:
I had to modify our flow. We were streaming data from Server B to Server A, but now Server B is sending signed URL to Server A and file is being downloaded directly from S3 using that signed url.

issues deleting an image using Cloud Functions for Firebase and #google-cloud/storage

I'm trying to create a script in Cloud Functions for Firebase that will react to a db event and remove an image that has its path in one of the params ("fullPath").
this is the code i'm using:
'use strict';
const functions = require('firebase-functions');
const request = require('request-promise');
const admin = require('firebase-admin');
const gcs = require('#google-cloud/storage')({
projectId: 'XXXXXXX',
credentials: {
// removed actual credentials from here
}});
admin.initializeApp(functions.config().firebase);
// Deletes the user data in the Realtime Datastore when the accounts are deleted.
exports.removeImageOnNodeRemoval = functions.database
.ref("images/{imageId}")
.onWrite(function (event) {
// exit if we are creating a new record (when no previous data exists)
if (!event.data.previous.exists()) {
console.log("a new image added");
return;
}
// exit if we are just trying to update the image
if (event.data.exists()) {
console.log("image is been modified");
return;
}
let previousData = event.data.previous.val();
if(!previousData || !previousData.fullPath){
console.log("no data in the previous");
return;
}
let bucketName = 'XXXXXXX';
console.log("default bucketName", gcs.bucket(bucketName));
let file = gcs.bucket(bucketName).file(previousData.fullPath);
console.log('the file /'+previousData.fullPath, file);
file.exists().then(function(data) {
let exists = data[0];
console.info("file exists", exists);
});
file.delete().then(function() {
// File deleted successfully
console.log("image removed from project", previousData.fullPath);
}).catch(function(error) {
// Uh-oh, an error occurred!
console.error("failed removing image from project", error, previousData);
});
});
the error i'm getting:
failed removing image from project { ApiError: Not Found
at Object.parseHttpRespBody (/user_code/node_modules/#google-cloud/storage/node_modules/#google-cloud/common/src/util.js:192:30)
at Object.handleResp (/user_code/node_modules/#google-cloud/storage/node_modules/#google-cloud/common/src/util.js:132:18)
at /user_code/node_modules/#google-cloud/storage/node_modules/#google-cloud/common/src/util.js:465:12
at Request.onResponse [as _callback] (/user_code/node_modules/#google-cloud/storage/node_modules/retry-request/index.js:120:7)
at Request.self.callback (/user_code/node_modules/#google-cloud/storage/node_modules/request/request.js:188:22)
at emitTwo (events.js:106:13)
at Request.emit (events.js:191:7)
at Request.<anonymous> (/user_code/node_modules/#google-cloud/storage/node_modules/request/request.js:1171:10)
at emitOne (events.js:96:13)
at Request.emit (events.js:188:7)
at IncomingMessage.<anonymous> (/user_code/node_modules/#google-cloud/storage/node_modules/request/request.js:1091:12)
at IncomingMessage.g (events.js:291:16)
at emitNone (events.js:91:20)
at IncomingMessage.emit (events.js:185:7)
at endReadableNT (_stream_readable.js:974:12)
at _combinedTickCallback (internal/process/next_tick.js:74:11)
at process._tickDomainCallback (internal/process/next_tick.js:122:9)
code: 404,
errors: [ { domain: 'global', reason: 'notFound', message: 'Not Found' } ],
response: undefined,
message: 'Not Found' } { contentType: 'image/png',
fullPath: 'images/1491162408464hznsjdt6oaqtqmukrzfr.png',
name: '1491162408464hznsjdt6oaqtqmukrzfr.png',
size: '44.0 KB',
timeCreated: '2017-04-02T19:46:48.855Z',
updated: '2017-04-02T19:46:48.855Z' }
i have tried with and without credentials to google-cloud/storage (thinking they might get auto filled while im in firebase.functions - do i need them?). i have tried adding a slash to the file's path. i have validated that the file actually exists in the bucket (even tho file.exists() returns false). the credentials i provided are for an iam i created with admin privileges for the storage service.
i have also enable the billing account on the free plan.
any ideas?
ok, so i got this solved. here are my conclusions:
you need to add to your buckets name the ".appspot.com". Its not written anywhere in the docs and getting your bucket name in firebase is hard enough for someone that is not familiar in the google cloud. I hope they will add this little peace of information into their docs or make it clear what is your bucket's name in firebase.
use the environment variable process.env.GCLOUD_PROJECT, it should have your project id that is identical to your bucket id in firebase. again, remember to add the .appspot.com suffix to it.
regarding the credentials to GCS, you don't need to provide them when using cloud functions for firebase. you seem to be authenticated already.
Make sure your bucket name doesn't include gs://
Eg. instead of gs://my-project-id.appspot.com use my-project-id.appspot.com
let bucket = gcs.bucket('my-project-id.appspot.com')
This may happen to you (as it did to me) if you copy your bucket name from, for instance, Android code, where you can use full URL to connect with storage, ie. storage.getReferenceFromUrl('gs://my-proj...
.
Also, it seems the projectId variable you use to initialise gcs doesn't need the appspot.com suffix (but it shouldn't break if you have it included). Ie. projectId:'my-project-id' should be suffice.
Lastly, the GCS node package docs states you need to generate separate JSON to pass as keyFilename to test things locally. Good news is - you can use the Firebase Admin SDK key, as described in the Get Started Server/Admin docs instead.

Resources