Twitter search API getting errors - node.js

I am trying to collect twitter search results.
I am using twitter search API with Nodejs.
Started with "quick start" given in twitter api site https://developer.twitter.com/en/docs/labs/recent-search/quick-start, but I am keeping get errors from my request.
this is my code:
const https = require('https');
const request = require('request');
const util = require('util');
const get = util.promisify(request.get);
const post = util.promisify(request.post);
const consumer_key = 'xxxxxxx'; // Add your API key here
const consumer_secret = 'xxxxxx'; // Add your API secret key here
const bearerTokenURL = new URL('https://api.twitter.com/oauth2/token');
const searchURL = new URL('https://api.twitter.com/labs/2/tweets/search');
async function bearerToken (auth) {
const requestConfig = {
url: bearerTokenURL,
auth: {
user: consumer_key,
pass: consumer_secret,
},
form: {
grant_type: 'client_credentials',
},
};
const response = await post(requestConfig);
return JSON.parse(response.body).access_token;
}
(async () => {
let token;
const query = 'obama';
const maxResults = 10;
try {
// Exchange your credentials for a Bearer token
token = await bearerToken({consumer_key, consumer_secret});
} catch (e) {
console.error(`Could not generate a Bearer token. Please check that your credentials are correct and that the Filtered Stream preview is enabled in your Labs dashboard. (${e})`);
process.exit(-1);
}
const requestConfig = {
url: searchURL,
qs: {
query: query,
max_results: maxResults,
format: 'compact',
},
auth: {
bearer: token,
},
headers: {
'User-Agent': 'LabsRecentSearchQuickStartJS',
},
json: true,
};
try {
const res = await get(requestConfig);
console.log(res.statusCode);
console.log(res);
if (res.statusCode !== 200) {
throw new Error(res.json);
return;
}
console.log(res.json);
} catch (e) {
console.error(`Could not get search results. An error occurred: ${e}`);
process.exit(-1);
}
})();
my error:
body: {
errors: [ [Object] ],
title: 'Invalid Request',
detail: 'One or more parameters to your request was invalid.',
type: 'https://api.twitter.com/labs/2/problems/invalid-request' }, [Symbol(kCapture)]: false } Could not get search results. An
error occurred: Error

There's a bug in this script which we need to fix. If you remove the line format: 'compact', then this will work - that parameter is no longer valid in Labs v2.

Related

Twitter request_token API showing { errors: [ { code: 32, message: 'Could not authenticate you.' } ] }

`
// Creates the timestamp in milliseconds
const timestamp = Math.round(Date.now() / 1000).toString();
// Percent encodes params
const encodedParams = encodeURIComponent(
`include_entities="true"&oauth_consumer_key=${process.env.TWITTER_CONSUMER_KEY}&oauth_nonce="${timestamp}"&oauth_signature_method="HMAC-SHA1"&oauth_timestamp="${timestamp}"&oauth_version="1.0"$status="hey guys"`
);
const perChangeEncodeParams = encodedParams.replace(/%/g, "%25");
// Combines the percent encoded string to match https://developer.twitter.com/en/docs/authentication/oauth-1-0a/creating-a-signature requirements
const oauth_signature = `POST&https%3A%2F%2Fapi.twitter.com%2F1.1%2Fstatuses%2Fupdate.json&${perChangeEncodeParams}`;
console.log('oauth_signature', oauth_signature);
// Creates signing key for hashing
const signingKey = `${encodeURIComponent(
process.env.TWITTER_CONSUMER_SECRET
)}&`;
console.log("sig", signingKey);
// Hashes string with signingKey then returns base64 string
const hashedSignature = crypto
.createHmac("sha1", signingKey)
.update(oauth_signature)
.digest("base64");
console.log("hash", hashedSignature);
const urlencodedSignature = encodeURIComponent(hashedSignature);
console.log("encodedhash", urlencodedSignature);
const data = "";
const config = {
method: "post",
url: "https://api.twitter.com/oauth/request_token?oauth_callback=https%3A%2F%2Flocalhost%3A3000%2Fintegration",
headers: {
Authorization: `OAuth oauth_consumer_key=${process.env.TWITTER_CONSUMER_KEY},oauth_nonce=${timestamp},oauth_signature="${urlencodedSignature}",oauth_signature_method="HMAC-SHA1",oauth_timestamp=${timestamp},oauth_version="1.0"`,
},
data: data,
};
axios(config)
.then(function (response) {
console.log(JSON.stringify(response.data));
})
.catch(function (error) {
console.log("???", error.response.data);
});
`
referred doc : twitter
When i try to do this it showing a error like could not authenticate you or bad authentication is there any way to do it correctly?
I need to fetch the request token to do twitter oauth

Extracting values from API data in node.js

Thank you for your time.
I'm trying to use OAuth2 in discord, but I'm having a hard time figuring out how to retrieve the username.
Can someone please tell me how to do it?
code
const fetch = require('node-fetch');
const express = require('express');
const app = express();
app.get('/', async ({ query }, response) => {
const { code } = query;
if (code) {
try {
const oauthResult = await fetch('https://discord.com/api/oauth2/token', {
method: 'POST',
body: new URLSearchParams({
client_id: process.env['ci'],
client_secret: process.env['cs'],
code,
grant_type: 'authorization_code',
redirect_uri: `https://oauth.aiueominato1111.repl.co`,
scope: 'identify',
}),
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
});
const oauthData = await oauthResult.json();
const userResult = await fetch('https://discord.com/api/users/#me', {
headers: {
authorization: `${oauthData.token_type} ${oauthData.access_token}`,
},
});
console.log( await userResult.json());
} catch (error) {
// NOTE: An unauthorized token will not throw an error;
// it will return a 401 Unauthorized response in the try block above
console.error(error);
}
}
return response.sendFile('index.html', { root: '.' });
});
app.listen(port, () => console.log(`App listening at http://localhost:${port}`));
thank you
You already have the JSON data (from await userResult.json()) with it you can either get the property from the object or destructure it.
Getting property
const user = await userResult.json();
const username = user.username
Destructuring
const { username, id } = await userResult.json()
You can find out more about what properties you can extract from the Discord documentation

Axios and Oauth1.0 - 'status: 400, Bad Request'

I'm new on Nodejs and all the modules related with Node. I've been trying to use axios for send a Oauth1.0 Autorization signature, but i'm getting: response: { status: 400, statusText: 'Bad Request', ...}
import { BASE_URL } from '../../../config/config.js';
import axios from 'axios';
import status from 'http-status';
import OAuth from 'oauth-1.0a';
import { createHmac } from 'crypto';
import dotenv from 'dotenv';
dotenv.config();
const CONSUMERKEY = process.env.consumer_key;
const CONSUMERSECRET = process.env.consumer_secret;
const TOKENKEY = process.env.access_token;
const TOKENSECRET = process.env.token_secret;
export const oauth = OAuth({
consumer: {
key: CONSUMERKEY,
secret: CONSUMERSECRET,
},
signature_method: 'HMAC-SHA1',
hash_function(base_string, key) {
return createHmac('sha1', key)
.update(base_string)
.digest('base64')
},
})
export const token = {
key: TOKENKEY,
secret: TOKENSECRET,
}
const doRequest = async (query) => {
const request_data = {
url: `${BASE_URL}`,
method: 'GET',
params: { q: `${query}` },
};
const authHeader = oauth.toHeader(oauth.authorize(request_data, token));
return await axios.get(request_data.url, request_data.params, { headers: authHeader });
};
const searchU = async (term) => {
return await doRequest(`${term}`);
};
export const userS = async (req, res, next) => {
try {
const { query } = req;
const { data } = await searchU(query.q);
const string = JSON.stringify(data);
const Rs = JSON.parse(string);
const response = {
code: 1,
message: 'sucess',
response: Rs
};
res.status(status.OK).send(response);
} catch (error) {
next(error);
if (error.response){
console.log("Response: ");
console.log(error.response);
} else if(error.request){
console.log("Request: ");
console.log(error.request)
} else if(error.message){
console.log("Message: ");
console.log(error.message)
}
}
};
I've been also trying the solution given On this post: but there's no way I can make this work, no idea what i could be doing wron...
When i try the following code (see below), using Request module (which is deprecated) works well, but I really need to do it with Axios...
const request_data = {
url: `${BASE_URL}`,
method: 'GET',
params: { q: `${query}` },
};
const authHeader = oauth.toHeader(oauth.authorize(request_data, token));
request(
{
url: request_data.url,
method: request_data.method,
form: request_data.params,
headers: authHeader,
},
function(error, response, body) {
console.log(JSON.parse(body));
}
)
Any thoughts on what I'm doing wrong on this?? Thank you very much!!
Refer to the following link for the Request Config for Axios. I believe you need to have the query params after the header in the axios.get()
Axios Request Config
Try, the following and see how it goes:-
return await axios.get(request_data.url, { headers: authHeader }, request_data.params);

Send email from G-Suite in nodejs server using Gmail API returns 400 bad request

I want to send an email from my G-Suite account in a nodejs server using Gmail API.
I know the credentials are ok, cause I have no problem to get messages/labels from my G-Suite.
this is my code:
const {GoogleAuth} = require('google-auth-library');
async sendMessage(to, from, subject, message) {
let raw = makeBody(to, from, subject, message);
let url = `https://www.googleapis.com/gmail/v1/users/${<MyEmail>}/messages/send`
let option = {
method: 'POST',
headers: {
'Content-Type': 'message/rfc822',
},
body: raw,
};
let client = await getClient()
client.request({url, option}, (res, err) => {
if (err) {
console.log('error', err);
} else {
console.log('res');
}
});
}
async getClient() {
try {
let auth = new GoogleAuth({
credentials: {
client_email: <clientEmail>,
private_key: <privateKey>,
},
scopes: [
"https://mail.google.com/",
"https://www.googleapis.com/auth/gmail.compose",
"https://www.googleapis.com/auth/gmail.modify",
"https://www.googleapis.com/auth/gmail.send"],
clientOptions: {subject: <myEmail>}
});
const client = await auth.getClient();
if (client)
return client
} catch (e) {
console.log('error accured while getClient', e);
return e;
}
}
I added the scopes of send, compose and modify to Admin Google, unfortunately I get this 400 bad request:
error [
{
domain: 'global',
reason: 'invalidArgument',
message: 'Invalid id value'
}
]
Use googleapis library.
const {google} = require('googleapis');
const gmail = google.gmail('v1');
async sendMessage(to, from, subject, message) {
let raw = makeBody(to, from, subject, message);
let client = await auth.getClient()
google.options({
auth: client
});
const res = await gmail.users.messages.send({
userId: 'me',
requestBody: {
raw: raw,
},
});
}

Google OAuth2 Service Account HTTP/REST Authentication

I am attempting to make a access token request using the documentation found below:
https://developers.google.com/identity/protocols/OAuth2ServiceAccount
I am leveraging the jsrsasign library to generate my JWT
For clarity I am deploying the code to Parse.com cloud code, everything executes fine with exception of the failed response from Google.
jsrsasign [http://kjur.github.io/jsrsasign/]
https://kjur.github.io/jsrsasign/api/symbols/KJUR.jws.JWS.html#.sign
Parse.Cloud.define("testBase", function(request, response) {
var createJWT = function(){
var creds = {
private_key_id: "532ca15e518a0<foobar>74dd81d48a9cb24",
private_key: "-----BEGIN PRIVATE KEY-----\nMIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcw<foobar>QCzxcu5ae3l7JXT\nZzI2kHA3lYay/2DIcC4KXqQWCMejQacRlFROftfnqRrf9qmEewH/0TMSMlOFt0G6\n9hjznhOHu3rxZcAxuK5bh7UnmoUWYksdtb+6VgCGF9Z5piTASrLxssILAUqY6EjT\nHKp3IQk6aqMqe6NhymCS/o0K9NvGA98znpv28ilD9dd5HXhfTdeGm7PDkZGIXIbR\nG+sQN8+tW46N1PaYnoz8iNGfvGk2Y04WDC2HJ590z4DAk41jbcWtnZnr/UyIJzTq\nTBjCWwAcF0qwSabf/mlWSf2S7DeCZKYNveMSN7F6meI8uYshuVoNqd95u/KGfQ4q\ns+wMdF3tAgMBAAECggEAcQ2MhnelUhisSBv3qfS/fVUdNmf/d02ExqSpz+mJkpNw\n+08qjYqbQGZKLloyVMv+f+ARm/nmKIsMXQTywBHC+nLeZ/yzFxGrJIh9VgCIfYEm\n9/IaNpZrEejfyfS/2+WeDv15pe4T+YDqe0jlsrEl2oTBQ7ApGRBqF0bZb/B4XVd3\ngZ6kya+UL5j+PSgNcaGABUfj7pDXZIRmVnWJxXSYhvvbD+SrXIhBMS3wXZ+vka1J\nkW/bwhzayu9/nI24WN7pALxf6/zB3Ewyoj5n1pnxbkvBMcK+PBiX9yAPvfH5cGQF\nQZx86L11maYpWHxufrbclow16qZHP41O+1eePGbIgQKBgQDmOY04z02RIMX32I7k\nbtokmG8qDnR8iu8dkLSRU4Ib7ZPzIBpjg9neaRib9A2fPVjyuxjvsUbob11BuklZ\nGCMu9SFV8w4LpUQ3clL+kBiGncuSmBfZWbj7uqLuzsNeeu3pihVTlkeWeagTAR36\nhi8K4IVQi5SmPF2dPiw9A8oXkQKBgQDH5j1smCFu9d+F2HIwDFXsW1wlyWhtcgfV\n70uCXdImnU25pJDARLX8vqaZp0KHIPmXLgUV/sU3oAX9NRdgV56bJTo7vwO3DATM\ntK14h7GZCKSYniOqX+3FdweNyn89qlHeAkZdvCZhGX5rOVXtlhpey7Eu8fQnPs1S\nbxd1EXRKnQKBgH+m1Yj0WLvpghskdkZuuIGmC600Cp6rol2wSI5z0SaPGoOp/zfC\neeD6QOzn602qBFHCL9dnYjuq0/iHw/ekjI2S2YMAm38Vibd8qkv/tbmecKu9rSuU\nth7No13qQyV138ioCZ8pKlRi7DBtZCPultLfHsxEOI3b1sRDHuBN45YhAoGAGbKe\niNxRx/rxvjoiC806KoVgJjdrJk63dSgrE9pNzssAF/Jw7Van8pLrxer7oXV6wJWY\n78ftwIXg3zk5BRieeiFiCBY5OwnfgBVmC42eJic3SatiuF9WqMDxhqfWja3ckmbG\ndvxeDrOBTfVz93QJddBHudo+4eCv8n33jQQuZ/0CgYEAsYXmQWOUndqBaZgho3ZV\njrRFmwiwiqJ1hqJdflBXbKlTQOpqea8QoQOQqyeMVQ1X7x3rDcHbhFSbd65GJT5j\n65B/OXrBpIBhb5u0/x6ytJhlM9sPRIL+G/m5QYnBY7dcQo6jlKxTUKHPEV/mwT2m\nt/ZxkAmz/9DKWFKtDc4ZshI\u003d\n-----END PRIVATE KEY-----\n",
client_email: "<foobar>-t18b3hrkab6urireblm8kb4kt45c92a2#developer.gserviceaccount.com",
client_id: "<foobar>-t18b3hrkab6urireblm8kb4kt45c92a2.apps.googleusercontent.com",
type: "service_account"
};
var header = {
alg:"RS256",
typ:"JWT"
};
var data = {
iss: creds.client_email,
scope:"https://www.googleapis.com/auth/analytics.readonly",
aud:"https://www.googleapis.com/oauth2/v3/token",
exp: KJUR.jws.IntDate.get('now + 1hour'),
iat: KJUR.jws.IntDate.get('now')
};
console.log("Preparing to generate RS256 JWT");
var sJWT = KJUR.jws.JWS.sign("RS256", JSON.stringify(header), JSON.stringify(data), creds.private_key);
console.log("RS256 JWT generation complete:");
console.log(sJWT)
return sJWT;
}
console.log("############################## ")
try{
console.log("Preparing assertion...")
var jwt = createJWT()
console.log("Assertion: "+jwt);
var options = {
method: 'POST',
headers: {
'Content-Type':'application/x-www-form-urlencoded'
},
url: "https://www.googleapis.com/oauth2/v3/token",
params: {
grant_type: "urn:ietf:params:oauth:grant-type:jwt-bearer",
assertion: jwt
}
};
console.log("------------------------");
console.log(options);
console.log("------------------------");
Parse.Cloud.httpRequest(options).done(function(rsp){
var r = (_.isString(rsp.text)) ? JSON.parse(rsp.text) : rsp.text;
console.log("Reponse from Google:");
console.log(rsp)
// console.log({ body: req.body, params: req.params, query: req.query, o: options, r: r });
// res.send(r);
response.success(r);
}).fail(function(err){
// console.error(err);
console.error("Failed response from Google:")
console.error(err.text)
response.error(err);
});
}catch(err){
console.error(err);
response.error(err);
}
});
The console output:
I2015-06-29T19:42:17.315Z]##############################
I2015-06-29T19:42:17.316Z]Preparing assertion...
I2015-06-29T19:42:17.317Z]Preparing to generate RS256 JWT
I2015-06-29T19:42:17.401Z]RS256 JWT generation complete:
I2015-06-29T19:42:17.402Z]eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiI2MDQ4Mjk2NTQ1MzktdDE4YjNocmthYjZ1cmlyZWJsbThrYjRrdDQ1YzkyYTJAZGV2ZWxvcGVyLmdzZXJ2aWNlYWNjb3VudC5jb20iLCJzY29wZSI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL2F1dGgvYW5hbHl0aWNzLnJlYWRvbmx5IiwiYXVkIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vb2F1dGgyL3YzL3Rva2VuIiwiZXhwIjoxNDM1NjEwNTM3LCJpYXQiOjE0MzU2MDY5Mzd9.nGbApndzwwtadeL2Jr2zU__JZrBZ6tYGJ17sTDksiSsFRXop_6CFAsV7fkXC6Xd-Nf3KfYzNuqGzLciQTzc9AhGNFTk_aUXU-ndMbYiVh3EpTkBI0olkS5rkgnmm3Q_yfaOswkyvMwE12RvgTTjymVzHGTZ8xC_x22Ep1n07Ap3TQn3WpeFeJlHciiwcxMTG7TsxAvHEgaqLzZ79feFmZanj6pqEH1kfZeJUQK1n3bwKtU92qpPn7b4dFtJs8I7El62HLExU1B2l7qdSyp4CRxmUPViUfWykElDZeqDzPoX38QEMDmmTgCYUXna7wJB6O0qC3aJpxkCAmzPCDkXkZQ
I2015-06-29T19:42:17.403Z]Assertion: eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiI2MDQ4Mjk2NTQ1MzktdDE4YjNocmthYjZ1cmlyZWJsbThrYjRrdDQ1YzkyYTJAZGV2ZWxvcGVyLmdzZXJ2aWNlYWNjb3VudC5jb20iLCJzY29wZSI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL2F1dGgvYW5hbHl0aWNzLnJlYWRvbmx5IiwiYXVkIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vb2F1dGgyL3YzL3Rva2VuIiwiZXhwIjoxNDM1NjEwNTM3LCJpYXQiOjE0MzU2MDY5Mzd9.nGbApndzwwtadeL2Jr2zU__JZrBZ6tYGJ17sTDksiSsFRXop_6CFAsV7fkXC6Xd-Nf3KfYzNuqGzLciQTzc9AhGNFTk_aUXU-ndMbYiVh3EpTkBI0olkS5rkgnmm3Q_yfaOswkyvMwE12RvgTTjymVzHGTZ8xC_x22Ep1n07Ap3TQn3WpeFeJlHciiwcxMTG7TsxAvHEgaqLzZ79feFmZanj6pqEH1kfZeJUQK1n3bwKtU92qpPn7b4dFtJs8I7El62HLExU1B2l7qdSyp4CRxmUPViUfWykElDZeqDzPoX38QEMDmmTgCYUXna7wJB6O0qC3aJpxkCAmzPCDkXkZQ
I2015-06-29T19:42:17.404Z]------------------------
I2015-06-29T19:42:17.405Z]{"method":"POST","headers":{"Content-Type":"application/x-www-form-urlencoded"},"url":"https://www.googleapis.com/oauth2/v3/token","params":{"grant_type":"urn:ietf:params:oauth:grant-type:jwt-bearer","assertion":"eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiI2MDQ4Mjk2NTQ1MzktdDE4YjNocmthYjZ1cmlyZWJsbThrYjRrdDQ1YzkyYTJAZGV2ZWxvcGVyLmdzZXJ2aWNlYWNjb3VudC5jb20iLCJzY29wZSI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL2F1dGgvYW5hbHl0aWNzLnJlYWRvbmx5IiwiYXVkIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vb2F1dGgyL3YzL3Rva2VuIiwiZXhwIjoxNDM1NjEwNTM3LCJpYXQiOjE0MzU2MDY5Mzd9.nGbApndzwwtadeL2Jr2zU__JZrBZ6tYGJ17sTDksiSsFRXop_6CFAsV7fkXC6Xd-Nf3KfYzNuqGzLciQTzc9AhGNFTk_aUXU-ndMbYiVh3EpTkBI0olkS5rkgnmm3Q_yfaOswkyvMwE12RvgTTjymVzHGTZ8xC_x22Ep1n07Ap3TQn3WpeFeJlHciiwcxMTG7TsxAvHEgaqLzZ79feFmZanj6pqEH1kfZeJUQK1n3bwKtU92qpPn7b4dFtJs8I7El62HLExU1B2l7qdSyp4CRxmUPViUfWykElDZeqDzPoX38QEMDmmTgCYUXna7wJB6O0qC3aJpxkCAmzPCDkXkZQ"}}
I2015-06-29T19:42:17.406Z]------------------------
I2015-06-29T19:42:17.504Z]Failed response from Google:
I2015-06-29T19:42:17.506Z]{
"error": "invalid_grant",
"error_description": "Bad Request"
}
Final Solution:
Import the google service account credentials json file (renamed to google-service-account-credentials.js), generate jwt, apply jwt as body in the Parse.Request instead of params.
var fs = require('fs');
var moment = require('moment');
var _ = require('underscore');
var KJUR = require("cloud/lib/jsrsasign/npm/lib/jsrsasign.js");
var googleServiceAccountCredentials = JSON.parse(fs.readFileSync('cloud/google-service-account-credentials.js'));
var createJWT = function(args, credentials){
var header = {
alg:"RS256",
typ:"JWT"
};
var now = moment().unix();
var defaults = {
iss: credentials.client_email,
scope:"https://www.googleapis.com/auth/analytics.readonly",
aud:"https://www.googleapis.com/oauth2/v3/token",
exp: now + (15*60),
iat: now
};
var data = {};
_.extend(data, defaults, args);
var sJWT = KJUR.jws.JWS.sign("RS256", JSON.stringify(header), JSON.stringify(data), credentials.private_key );
return sJWT;
};
Parse.Cloud.define("testBase", function(request, response) {
try{
var now = moment().unix();
var options = {
method: 'POST',
headers: {
'Content-Type':'application/x-www-form-urlencoded'
},
url: "https://www.googleapis.com/oauth2/v3/token",
body: {
grant_type: encodeURI("urn:ietf:params:oauth:grant-type:jwt-bearer"),
assertion: createJWT({
exp: now + (60*60),
iat: now
}, googleServiceAccountCredentials)
}
};
Parse.Cloud.httpRequest(options).done(function(rsp){
var r = (_.isString(rsp.text)) ? JSON.parse(rsp.text) : rsp.text;
console.log("Reponse from Google:");
console.log(r.access_token);
console.log(r.expires_in);
console.log(r.token_type);
response.success(r);
}).fail(function(err){
console.error("Failed response from Google:")
console.error(err.text)
response.error(err);
});
}catch(err){
console.error(err);
response.error(err);
}
});
Use body instead of params in your request options

Resources