Unable to load default credentials in node.js google translate - node.js

I need to translate some text in node.js using google translate. I end up getting the following Error: Could not load the default credentials. Browse to here to get more details. This problem has costed me more than 48 hours. I have followed all the instructions in that link but problem still persists. Please someone point what is it that I've missed.
Error log:
ERROR: Error: Could not load the default credentials. Browse to
https://developers.google.com/accounts/docs/application-default-credentials
for more information.
at /user_code/node_modules/#google-cloud/translate/node_modules/google-auth-library/lib/auth/googleauth.js:316:21
at /user_code/node_modules/#google-cloud/translate/node_modules/google-auth-library/lib/auth/googleauth.js:346:7
at Request._callback (/user_code/node_modules/#google-cloud/translate/node_modules/google-auth-library/lib/transporters.js:70:30)
at self.callback (/user_code/node_modules/#google-cloud/translate/node_modules/request/request.js:186:22)
at emitOne (events.js:96:13)
at Request.emit (events.js:188:7)
at Request.onRequestError (/user_code/node_modules/#google-cloud/translate/node_modules/request/request.js:878:8)
at emitOne (events.js:96:13)
at ClientRequest.emit (events.js:188:7)
at Socket.socketErrorListener (_http_client.js:309:9)
function translateText(Text, Target) {
// [START translate_translate_text]
// Imports the Google Cloud client library
const Translate = require('#google-cloud/translate');
// Your Google Cloud Platform project ID
const projectId = 'xxxxxxxxxx';
// Instantiates a client
const translate = new Translate({
projectId: projectId,
});
// Translates some text into Russian
translate
.translate(Text, Target)
.then(results => {
const translation = results[0];
console.log(`Text: ${text}`);
console.log(`Translation: ${translation}`);
return translation;
})
.catch(err => {
console.error('ERROR:', err);
});
}

Related

Some error occures after send request to the function url

I set up a one firebase function to send messages to my bot. But when firebase gets request I can see that some error occurred.
FetchError: request to https://api.telegram.org/bot<BOT-TOKEN>/getMe failed, reason: getaddrinfo EAI_AGAIN api.telegram.org:443
at ClientRequest.<anonymous> (/srv/node_modules/node-fetch/lib/index.js:1453:11)
at emitOne (events.js:116:13)
at ClientRequest.emit (events.js:211:7)
at TLSSocket.socketErrorListener (_http_client.js:401:9)
at emitOne (events.js:116:13)
at TLSSocket.emit (events.js:211:7)
at emitErrorNT (internal/streams/destroy.js:66:8)
at _combinedTickCallback (internal/process/next_tick.js:139:11)
at process._tickDomainCallback (internal/process/next_tick.js:219:9)
and
Error: Can't set headers after they are sent.
at validateHeader (_http_outgoing.js:491:11)
at ServerResponse.setHeader (_http_outgoing.js:498:3)
at ServerResponse.header (/worker/node_modules/express/lib/response.js:767:10)
at ServerResponse.contentType (/worker/node_modules/express/lib/response.js:595:15)
at ServerResponse.sendStatus (/worker/node_modules/express/lib/response.js:357:8)
at /srv/index.js:30:13
at <anonymous>
at process._tickDomainCallback (internal/process/next_tick.js:229:7)
But secound one I suppose does not influence on the result.
As a result, I don't get any message to my to Bot.
The next script that i use:
const functions = require('firebase-functions');
const telegraf = require('telegraf');
const axios = require('axios');
const bot = new telegraf('<BOT-TOKEN>')
bot.start((ctx) => ctx.reply('Welcome!'))
bot.help((ctx) => ctx.reply('Send me a sticker'))
bot.on('sticker', (ctx) => ctx.reply('👍'))
bot.hears('hi', (ctx) => ctx.reply('Hey there'))
bot.launch()
exports.helloWorld = functions.https.onRequest((request, res) => {
const token = '<BOT-TOKEN>';
const url = `https://api.telegram.org/bot${token}/sendMessage`;
axios.post(url, {
chat_id: '154866113',
text: "just do it!"
})
.then(function (response) {
console.log(response);
res.send({ status: "O"});
return 'ok';
})
.catch(function (error) {
console.log(error);
res.sendStatus(500);
});
res.send("Hello from Firebase!");
});
The getaddrinfo EAI_AGAIN error means that you need to switch to the "Flame" or "Blaze" pricing plan.
As a matter of fact, the free "Spark" plan "allows outbound network requests only to Google-owned services". See https://firebase.google.com/pricing/ (hover your mouse on the question mark situated after the "Cloud Functions" title)
The telegram API is not a Google-owned service, so you need to switch to the "Flame" or "Blaze" plan.
I'm guessing the answer to the EAI_AGAIN error is due to a malformed URI. Are you sure https://api.telegram.org/bot<BOT-TOKEN>/getMe is the correct URI and is accessible from where ever this script is being run from?
The second error is due to you calling the res.send() method more than once. Express res objects wrap Node's ServerResponse object, and once the connection is closed via write or end, it cannot be sent again. Try removing the res.send("Hello from Firebase!"); section of your code and coming back.

how to use node pg in AWS Lambda?

UPDATE/SOLVED ... the problem was that pgpass plugin was looking for $HOME/.pgpass, and $HOME wasn't defined on lambda, causing failure of join(undefined, '.pgpass'). Not really worth crediting myself with an answer for that ....
I have the following test code in a lambda handler (compiled from typescript):
const db = new Pool()
const {rows} = await db.query('select 1 as x')
console.log('rows', JSON.stringify(rows))
The connection is created via PGHOST PGPORT PGUSER PGDATABASE in the environment. I know the configuration is "almost right" because the first time I tried it I got:
{"errorMessage":"error: no pg_hba.conf entry for host \"10.1.1.249\",
user \"foo\", database \"bar\", SSL off\n at
Connection.parseE (/var/task/handler.js:9209:11)\n at
Connection.parseMessage (/var/task/handler.js:9034:19)\n at
Socket. (/var/task/handler.js:8777:22)\n at emitOne
(events.js:96:13)\n at Socket.emit (events.js:188:7)\n at
readableAddChunk (_stream_readable.js:176:18)\n at
Socket.Readable.push (_stream_readable.js:134:10)\n at TCP.onread
(net.js:547:20)"}
That seemed hopeful. I changed the postgres config to allow from the subnet, and tried again. However, now I get:
2018-02-06 18:14:21.183 (-05:00) 76761ca5-0b93-11e8-8783-a74d098c9f4a select
2018-02-06 18:14:21.202 (-05:00) 76761ca5-0b93-11e8-8783-a74d098c9f4a TypeError: Path must be a string. Received undefined
at assertPath (path.js:7:11)
at Object.join (path.js:1211:7)
at Object.module.exports.getFileName (/var/task/handler.js:32434:16)
at module.exports (/var/task/handler.js:32355:23)
at Connection.<anonymous> (/var/task/handler.js:31255:9)
at emitOne (events.js:96:13)
at Connection.emit (events.js:188:7)
at Socket.<anonymous> (/var/task/handler.js:8781:12)
at emitOne (events.js:96:13)
at Socket.emit (events.js:188:7)
END RequestId: 76761ca5-0b93-11e8-8783-a74d098c9f4a
What is going on? It seemed as if it had got to the database and connected the first time... Now it fails on the query. Is there some option I should be using?
First, you are not calling pool.connect to acquire a client from the pool.
Second, the current Node.js runtime 6.10 on AWS Lambda does not support async functions. (Unless you transpile your code down to ES5 using Babel directly or some other boilerplate that uses Babel such as es2017-lambda-boilerplate)
Having said that, you'll have to use either callbacks or promises (then/catch). For example:
const {Pool} = require("pg");
const db = new Pool({
host: "localhost",
user: "database-user",
// ... rest of config options
});
db.connect((err, client, release) => {
if (err) {
console.error("Error acquiring client.", err.stack);
} else {
client.query("SELECT 1 AS x", (err, result) => {
release();
if (err) {
console.error("Error executing query.", err.stack);
} else {
console.log(result.rows);
}
})
}
})

Firebase: Delete files in Cloud Starage using Cloud Functions

I'm trying to delete all files, related to some specific entry in Realtime Database, from Cloud Storage on the entry deletion, using Cloud Functions. My functions looks as fallows:
exports.onDeleteRequest = functions.database.ref('/requests/{requestid}/').onDelete(event => {
const storage = functions.config().firebase.storageBucket;
const userId = event.data.previous.child('uid').val();
const requestId = event.params.requestid;
const path = storage + '/photos/' + userId + '/' + requestId;
console.log('path: ', path);
return gcs.bucket(path).delete().then(function() {
console.log("Files removed");
}).catch(function(error) {
console.error("Failed removing files", error);
});
});
But, I continue getting following error in log:
Failed removing files { 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:182:7)
at Request.self.callback (/user_code/node_modules/#google-cloud/storage/node_modules/request/request.js:186: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:1163:10)
at emitOne (events.js:96:13)
at Request.emit (events.js:188:7)
code: 404,
errors: [ { domain: 'global', reason: 'notFound', message: 'Not Found' } ],
response: undefined,
message: 'Not Found' }
path: photos/gRplE2ujnIb93Ji5HSzEj3O4i3d2/-L-DHkKMhvLH9l6dWmR2
All subfolders are 100% existing at the time of the function execution. Can anyone help?
I apologize for asking the question, that, without a doubt, was asked before in one way or another, but I didn't find any suggestion of how to solve this issue or why does it occurs in the first place.

Node googleapis: getting Error: invalid_request after short period of time

I'm using the node googleapis library to make requests to the youtube data api. I'm starting of with authenticating a user using passport the passport-youtube-v3 library. Everything works fine. I'm able to authenticate and I can make authorized requests to the youtube data api. But after a certain amount of time (around 1-2h) the credentials seem to have expired or just become invalid and I get the following error:
{ Error: Invalid Credentials
at Request._callback (/Users/flavio/Code/BA/node_modules/google-auth-library/lib/transporters.js:85:15)
at Request.self.callback (/Users/flavio/Code/BA/node_modules/request/request.js:188:22)
at emitTwo (events.js:106:13)
at Request.emit (events.js:191:7)
at Request.<anonymous> (/Users/flavio/Code/BA/node_modules/request/request.js:1171:10)
at emitOne (events.js:96:13)
at Request.emit (events.js:188:7)
at IncomingMessage.<anonymous> (/Users/flavio/Code/BA/node_modules/request/request.js:1091:12)
at IncomingMessage.g (events.js:286:16)
at emitNone (events.js:91:20)
at IncomingMessage.emit (events.js:185:7)
at endReadableNT (_stream_readable.js:926:12)
at _combinedTickCallback (internal/process/next_tick.js:74:11)
at process._tickCallback (internal/process/next_tick.js:98:9)
code: 401,
errors:
[ { domain: 'global',
reason: 'authError',
message: 'Invalid Credentials',
locationType: 'header',
location: 'Authorization' } ] }
I understand that auth tokens expire after some time. But according to the documentation this shouldn't happen before 6 months of inactivity. Also I'm not making an excessive amount of requests that could render the tokens invalid. Nevertheless I tried to implement a manual toke refresh of the access token like this:
const fetch = (user, ressource, operation, opts) => {
let oauth2Client = new OAuth2();
let client = google.youtube({ version: 'v3',auth: oauth2Client })[ressource][operation];
oauth2Client.credentials = {
access_token: user.youtube.token,
refresh_token: user.youtube.refreshToken
};
return new Promise((success, failure) => {
client(opts, function(err, data, response) {
if (err)
if(err.code === 401)
oauth2Client.refreshAccessToken(function(err, tokens) {
console.log(err);
});
else
failure(err);
if (data)
success(data);
});
});
}
I'm not sure if I implemented this correctly of if it even makes sense to do this. I get the following error:
{ Error: invalid_request
at Request._callback (/Users/flavio/Code/BA/node_modules/google-auth-library/lib/transporters.js:81:15)
at Request.self.callback (/Users/flavio/Code/BA/node_modules/request/request.js:188:22)
at emitTwo (events.js:106:13)
at Request.emit (events.js:191:7)
at Request.<anonymous> (/Users/flavio/Code/BA/node_modules/request/request.js:1171:10)
at emitOne (events.js:96:13)
at Request.emit (events.js:188:7)
at IncomingMessage.<anonymous> (/Users/flavio/Code/BA/node_modules/request/request.js:1091:12)
at IncomingMessage.g (events.js:286:16)
at emitNone (events.js:91:20)
at IncomingMessage.emit (events.js:185:7)
at endReadableNT (_stream_readable.js:926:12)
at _combinedTickCallback (internal/process/next_tick.js:74:11)
at process._tickCallback (internal/process/next_tick.js:98:9) code: 400 }
What else could be the issue when getting the first error? Is it possible that the access token expires so quickly? If so, how do I refresh it correctly?
Any help is greatly appreciated!
It seems like the problem was that I didn't instantiate OAuth2 correctly. I didn't pass the credentials of my app to the constructor upon creation. Everything seems to work now.
let oauth2Client = new OAuth2(
clientID,
clientSecret,
callbackURL
);
The only confusion I still have is as to why it worked for a couple of requests before it started to throw the error described above.

Cloud Functions for Firebase Image download function Error

I am building a web application using Firebase and the new feature Cloud Functions for Firebase. I have created a function that takes a URL and downloads the image into a 64-bit encoded string as below using the node modules request and request-promise-native:
module.exports = {
downloadImageFromUrl: function (url) {
var options = {
method: 'GET',
uri: url,
resolveWithFullResponse: true,
simple: false,
family: 4
};
return rp.get(options)
.then(function (res) {
return "data:" + res.headers["content-type"] + ";base64," + new Buffer(res.body).toString('base64');
})
.catch(function (error) {
console.log("ERROR GETTING image", error);
return error;
});
}
};
The top function works perfectly running locally but once on firebase it gives the error:
RequestError: Error: getaddrinfo EAI_AGAIN lh6.googleusercontent.com:443
at new RequestError (/user_code/node_modules/request-promise/node_modules/request-promise-core/lib/errors.js:14:15)
at Request.plumbing.callback (/user_code/node_modules/request-promise/node_modules/request-promise-core/lib/plumbing.js:87:29)
at Request.RP$callback [as _callback] (/user_code/node_modules/request-promise/node_modules/request-promise-core/lib/plumbing.js:46:31)
at self.callback (/user_code/node_modules/request/request.js:188:22)
at emitOne (events.js:96:13)
at Request.emit (events.js:188:7)
at Request.onRequestError (/user_code/node_modules/request/request.js:884:8)
at emitOne (events.js:96:13)
at ClientRequest.emit (events.js:188:7)
at TLSSocket.socketErrorListener (_http_client.js:310:9)
at emitOne (events.js:96:13)
at TLSSocket.emit (events.js:188:7)
at connectErrorNT (net.js:1020:8)
at _combinedTickCallback (internal/process/next_tick.js:74:11)
at process._tickDomainCallback (internal/process/next_tick.js:122:9)
I am calling the function in the firebase auth trigger when a user is created as below:
exports.createUser = functions.auth.user().onCreate(event => {
if (event.data.photoURL) {
utils.downloadImageFromUrl(event.data.photoURL)
.then(function(res){
console.log("User Photo", res);
})
.catch(function(error){
console.log("Error", error);
})
}
});
Any help would be greatly appreciated.
Not entirely sure yet if this is the answer, but after reading the documentation, I read their free plan which says you cannot make any out bound requests. So I guess getting an image from a Url counts as an outbound request. After I start paying for their service, I will come back to verify if this was the problem.

Resources