nodejs gmail api not supporting promises - node.js

Google recommends using promises, but its code examples do not, and I'm struggling to make the gmail api work with promises when I modify the code from the online docs.
All I've changed are the lines below, but I get an error
VM677:5 Uncaught TypeError: gmail.users.messages.list(...).then is not a function
gmail.users.messages.list({
auth: auth,
userId: 'me',
labelIds: 'Label_14'
// }, function(err, response) {
// if (err) {
// console.log('The API returned an error: ' + err);
// return;
// }
// console.log(response);
})
.then(response => {
console.log("success", response);
})
Most of the examples of SO use promises so I think it should be possible but I can't see what the problem is. Would really welcome some help

The googleapis module does not support promises.
Consider using util.promisify if you want to use promises with this module.
var list = util.promisify(gmail.users.messages.list);
list({
auth: auth,
userId: 'me',
labelIds: 'Label_14'
})
.then(...);

Related

TypeError: Cannot read property 'then' of undefined when using JWT token and refresh token

Sorry I'm new to backend (nodejs) and I'm trying to build a JWT token and refresh token but I stumbled across an error that I cannot fix when I try to run an endpoint in insomnia.
TypeError: Cannot read property 'then' of undefined
This is the code snippet from the area the error came from in my app.js file
app.post('/users/login', (req, res) => {
let email = req.body.email;
let password = req.body.password;
User.findByCredentials(email, password)
.then((user) => {
return user.createSession()
.then((refreshToken) => {
return user.generateAccessAuthToken()
.then((accessToken) => {
return { accessToken, refreshToken };
});
})
.then((authTokens) => {
res
.header('x-refresh-token', authTokens.refreshToken)
.header('x-access-token', authTokens.accessToken)
.send(user);
})
}).catch((e) => {
res.status(400).send(e);
});
});
And this is the code for the method "findByCredentials" in my user.model.js file
UserSchema.statics.findByCredentials = function(email, password) {
let User = this;
User.findOne({ email }).then((user) => {
if(!user) return Promise.reject();
return new Promise((resolve, reject) => {
bcrypt.compare(password, user.password, (err, res) => {
if (res) resolve(user);
else {
reject();
}
})
})
});
}
Please help me
Error solved: I just needed to return the value of the findByCredentials method to solve the problem
Since the error isn't posted, it's hard to pinpoint the error line & cause.
But I would suggest using .catch blocks along with the end of every .then chain and get the spot/line of error
Recommendation:
You are creating a callback hell by using nested .then chains what is call back hell.
Try using async/await syntax to achieve the same functionality in a simplified way - Ref.
Regards,
Muhamed
As if you didn't send any code snippet, it is quite clear. But after going through your code it seems after resolving the "user" you are calling two methods createSession and generateAccessAuthToken. And as you also didn't send any code snippet of these methods I'm assuming you are having error from one of the functions.
And a piece of advice:
Practice best error handling patterns. It will help you in your journey.
https://www.youtube.com/watch?v=cFTFtuEQ-10
And async js:
https://www.youtube.com/watch?v=PoRJizFvM7s

Reactjs + Express Twitter API "Could not authenticate you."

I am trying to create a very simple app that allows me to post a tweet. I am currently using React running on port 3000 and express server.js running on port 5000
my server.js has the following:
app.post("/twitter/message", async(req, res) => {
const tweet = req.body.tweet;
try {
const response = await postToTwitter(tweet);
res.json({
message: 'Tweet successfully posted to twitter'
});
} catch (error) {
res.status(500).json({
message: 'Not able to post'
});
}
});
function postToTwitter(tweet) {
client.post(
"statuses/update",
{ status: tweet },
function (error, tweet, response) {
if (error) log(error);
/* log(tweet); // Tweet body. */
}
);
}
I am then using a script on the index.html page to post the input tweet:
<script>
$('button').on('click', (event) => {
event.preventDefault();
const tweet = $('#tweet').val();
// Post Tweet
$.ajax({
url: '/twitter/message',
method: 'POST',
data: {
tweet
}
})
.then(() => {
alert('Data successfully posted');
console.log('Data successfully posted');
})
.catch((error) => {
alert('Error: ', error);
console.log('Error: ', error);
});
})
</script>
This however is giving me the bellow error when I hit the post button:
[ { code: 32, message: 'Could not authenticate you.' } ]
If I use this exact same setup with just express it works perfectly fine, the issue occurs when trying to use react. Any help would be amazing.
It is possibly a CORS issue (which would show up in the frontend but not in Node/Backend).
If you're using some sort of API key to make the API request you're not showing it in this sample (don't show people your API key). By similar logic, do not have your API key on the client side, as anyone downloading your website would then have your Twitter API key. Instead, for multiple reasons it is better to have the backend be the one to make the API requests with your API key.
On the other hand if users are supposed to authenticate via O-Auth and you're supposed to pass a cookie with your authentication make sure you useCredentials on the request. axios.post(BASE_URL + '/api', { withCredentials: true }); . Looks like you're using jquery so add the same withCredentials:
Try adding this to your options:
crossDomain: true,
xhrFields: {
withCredentials: true
},
If you don't see a cookie when you type document.cookie in the browser that's probably a sign you're not authenticated in your computer.

How to validate request body in Node.js, Express - is it possible without using a library?

I have the code (below) and one developer said to me that I had to validate my request:
router.post('/dashboard', passport.authenticate('jwt', { session: false }),
(req, res) => {
try {
let newPost = new Post({
category: req.body.category,
title: req.body.title,
photo: req.body.photo,
text: req.body.text,
author: req.body.author,
date: req.body.date
});
Post.addPost(newPost, (err, user) => {
if (err) {
res.json({success: false, msg: `Post has not been added. ${err}`})
} else {
res.json({success: true, msg: 'Post was added.'})
}
})
} catch (err) {
const error = (res, error) => {
res.status(500).json({
success: false,
message: error.message ? error.message : error
})
}
console.log('error routes/auth POST', res, error)
}
})
I googled and found the solutions i.e. using libraries for request validation like express-validator - is it ok?
Are there any native, built-in express, node.js methods to validate a request?
Or it's better to use a library like express-validator?
Express.js doesn't have a built-in validator.
But you can use express-validator or joi. Both of these libraries are good.
if you are using typescript in your project class-validator is a better option, it will let you use types.
And this is a great talk on why you need to validate the data. Take Data Validation Seriously by Paul Milham
This is a bit late!
Unfortunately, ExpressJs does not have build-in validation. You can use Zod to validate your request's (params, query or body) payloads by creating a custom middleware or use a package like zod-express-middleware
As mentioned above Express.js does not have its own built-in validator. You can also check this library simple-body-validator, it offers an experience similar to the Laravel validation

opentok interconnect with node js express

I am implementing opentok interconnect with nodejs express.
Getting error:
No callback given to dial, while implementing dial-out.
My use case is as per documentation.
I am able to get all required values like config, sessionId, token, auth. , but still unable to connect the call.
opentok.dial(sessionId, token, config.uri, options, {
auth: {
username: config.uname, password: config.pass }
},
function (err, sipCall) {
if (err)
return res.status(500).send('Platform error starting SIP Call:'+err);
res.send(sipCall);
});
It looks like you are posting too many arguments into the function before the callback.
From the github repo we can see the example:
opentok.dial(sessionId, token, sipUri, options, function (error, sipCall) {
We can see the arguments:
sessionId
token
sipUri
options
callback
You however are passing in an object between options and the callback.
opentok.dial(sessionId, token, config.uri, options,
// Extra object argument, is this meant to be options?
{
auth: {
username: config.uname, password: config.pass}
},
function (err, sipCall) {
if (err)
return res.status(500).send('Platform error starting SIP
Call:'+err);
res.send(sipCall);
});

unofficial vine api not working

I am trying to connect to the vine API to retrieve the list of uploaded videos of a given user.
I'm using a node.js module called Vineapple.
The problem is some of the api endpoints seems to not work anymore
Here is a snippet that works
var vine = new vineapple({
key: 'some-key',
userId: '123456789',
username: 'user',
});
vine.me(function(err, response){ // calls 'https://api.vineapp.com/users/me'
if(err) throw err;
console.log(response);
});
This logs the whole vine user's settings:
{ followerCount: 300,
includePromoted: 2,
userId: '123456789',
private: 0,
likeCount: 30,
... etc }
And here is a snippet that does not work
var vine = new vineapple({
key: 'some-key',
userId: '123456789',
username: 'user',
});
vine.user(connectionObject.userId.toString(), function(err, response){ // calls 'https://api.vineapp.com/timelines/users/{userId}'
if(err) throw err;
console.log(response);
});
This never return anything.
Are all the vine api endpoints still available?
If yes, what could be my problem?
If no, is there another solution to retrieve vine videos?
Thanks
For those who are wondering.
As for today (april 2014), the vine unofficial api is still up. You can test it if here : https://api.vineapp.com/timelines/users/920890957405237248
I had a problem with the node.js vineapple module:
1/ You should always call vineapple functions with promise syntax:
https://github.com/furf/vineapple#promises
2/ Vine use big int as user ids, js cannot handle those so you should send userId as js strings and not numbers (I stored it as ints. The .toString() was useless here)
3/ There is a known bug in vineapple module, you should comment line 121 of vineapple.js: https://github.com/furf/vineapple/issues/2
As a conclusion, here is how my code look like:
var vine = new vineapple({
key: key,
userId: userId, // Stored as String !
username: username,
});
options= {page: '1', size: '20'};
vine.user(userId, options).then(function (response) {
console.log('SUCCESS', response);
}).fail(function (error) {
console.log('ERROR', error);
});
Hope it helps

Resources