Mirror API and Node.JS - google-api-client

I have a node.js program that I am trying to work with the googleapis module (https://github.com/google/google-api-nodejs-client) version 0.2.5-alpha.
I can make calls using the raw HTTP without problems, so I know I am white listed for the API, I am authenticating and authorizing correctly, and the correct scopes and everything are being requested. If I use the same access_token to do an insert into the timeline, I am getting an error in the callback. I am also discovering the plus API, and calls using this API are working fine.
Code fragment to discover the API, which appears to work without problems:
var client;
googleapis
.discover( 'plus', 'v1' )
.discover( 'mirror', 'v1' )
.execute( function(err,data){
console.log( err );
client = data;
});
Code fragment to do the call:
client.mirror.timeline.insert({
text: "test 1 "
} ).withAuthClient(user.auth).execute(function(err,result,res){
console.log( '++ start ++' );
console.log( '+err ', err );
console.log( '+result', result );
//console.log( '+res ', res );
console.log( '++ end ++' );
});
What is logged during the callback:
++ start ++
+err { code: 400,
message: 'Required',
data: [ { domain: 'global', reason: 'required', message: 'Required' } ] }
+result undefined
++ end ++
Any indication what is "Required", how to provide it, or how to further debug errors such as this?

UPDATE: the resource property is no longer required so the original code should just work instead of the proposed solution.
Since the node.js client library is based on the JavaScript client library, you need to set the request body in the "resource" property:
client.mirror.timeline.insert({resource: {
text: "test 1 "
}}).withAuthClient(user.auth).execute(function(err,result,res){
console.log( '++ start ++' );
console.log( '+err ', err );
console.log( '+result', result );
//console.log( '+res ', res );
console.log( '++ end ++' );
});

Related

How to load data from remote URI with nestjs/axios properly using Observables in the correct way?

NestJs suggests to use the HttpModule imported from #nestjs/axios to perform requests to external APIs. I understand that the HttpService transforms the responses into Observables. However, it makes it hard to fetch data inside of my service that wants to fetch data from a remote service and immediately work with these data:
try {
const metaData = await this.httpService.get(tokenUri).pipe(
map((res) => res.data),
catchError((e) => {
throw new HttpException(e.statusText, e.status);
}),
);
console.log("---------------")
console.log(metaData);
console.log("---------------")
} catch (e) {
this.logger.error(`Unable to fetch MetaData from ${tokenUri}. ` + e.toString());
}
What I get is this:
---------------
Observable {
source: Observable {
source: Observable { _subscribe: [Function (anonymous)] },
operator: [Function (anonymous)]
},
operator: [Function (anonymous)]
}
---------------
The reason why I don't want to use subscribe directly after the execution of get is that this way I was not able to catch 404 errors. On the internet I found the combination of pipe and catchError in order to do so. This way I am able again to catch the errors but I don't get any data anymore.
Thus, I have still to execute subscribe to subscribe on my data.
So I came up with this:
this.logger.debug('Found Token-URI: ' + tokenUri);
try {
const metaData = await this.httpService.get(tokenUri).pipe(
map((res) => res.data),
catchError((e) => {
throw new HttpException(e.statusText, e.status);
}),
);
metaData.subscribe((x) => {
// here is my data:
console.log(x);
});
} catch (e) {
this.logger.error(`Unable to fetch MetaData from ${tokenUri}. ` + e.toString());
}
This way it works, but I am not sure if it is the right way from the nextjs/axios developers point of view.
I think in this case you can simplify your code by using an error-handler that you can provide to the .subscribe function. So instead of having to use try/catch and rethrowing the error, you could simply do:
this.logger.debug('Found Token-URI: ' + tokenUri);
const metaData$ = this.httpService.get(tokenUri).pipe(map((res) => res.data));
metaData$.subscribe(
(x) => console.log(x),
(err) => this.logger.error(`Unable to fetch MetaData from ${tokenUri}. ` + e.toString())
);
As a side note, I'd recommend reading this blog-post regarding rxjs error-handling.

Nodemailer. createTestAccount and cypress: generate same email address

I created an E2E to test for signups, using Nodemailer with Ethereal.
When the test runs the first time everything ends smoothly, but when I executed it a second time the test, for some reason, breaks.
While investigating the above issue, I noticed that the createTestAccount returns the same email address (unless cypress is restarted).
Here's the function code for createTestAccount: https://github.com/nodemailer/nodemailer/blob/master/lib/nodemailer.js#L58.
Is createTestAccount using an internal cache?
If yes, is there a way to disable it (besides setting and process.env.ETHEREAL_CACHE to false)?
Based on the current version (6.7.4) of code, it's not possible to disable the cache any other way than setting the env variable ETHEREAL_CACHE to something different than ['true', 'yes', 'y', '1'].
Aka process.env.ETHEREAL_CACHE needs to be false
Keep in mind that this is OS level env variable. Not the ones setup in Cypress.
And the best thing is the great documentation which mentions ETHEREAL_CACHE variable ...
const request = require("request");
async function createEmail (callback) {
request.post({
headers: { "content-type" : "application/json" },
method: "POST",
url: "https://api.nodemailer.com/user",
body: Buffer.from(
JSON.stringify({
requestor: "nodemailer",
version: "6.7.8"
})
)
}, (err, res, body) => {
if(err)
return callback("Failed to handle request!");
const data = JSON.parse(body) || null;
if(typeof(data) !== "object" || typeof(data.status) !== "string")
return callback("Failed to resolve data");
delete data.status;
return callback(false, data);
});
};
createEmail((err, account) => {
if(err)
return console.log(err);
console.log(account);
});

Redux Toolkit - do not send request when query param is invalid

I've checked the redux toolkit docs and don't see an example of this typical use case: do not send the request of the query has an invalid param.
For example, a get request to endpoint /categories/{name} requires a name value. If name does not have a value, then the request should not be made.
const baseQuery = fetchBaseQuery({
baseUrl: Constants.PATHWAY_API_URL
});
export const pathwayApi = createApi({
reducerPath: 'pathwayApi',
baseQuery: baseQueryWithReAuth,
endpoints: builder => ({
getSubCategories: builder.query({
// NETWORK REQUEST SHOULD NOT BE MADE IF "name" param is falsy
query: name => `${Constants.PATHWAY_API.CATEGORIES_PATH_NAME}/${name}`,
}),
}),
});
I want to add this type of param validation to all my queries that require a param value or values. What's the recommended approach / pattern for handling this validation at the createApi (or possibly fetchBaseQuery) layer?
Thanks in advance!
You can actually throw an error in your query function.
export const pathwayApi = createApi({
reducerPath: "pathwayApi",
baseQuery: baseQueryWithReAuth,
endpoints: (builder) => ({
getSubCategories: builder.query({
// NETWORK REQUEST SHOULD NOT BE MADE IF "name" param is falsy
query: (name) => {
if (!name) {
throw new Error("Category name is required.");
}
return `${Constants.PATHWAY_API.CATEGORIES_PATH_NAME}/${name}`;
}
})
})
});
When this happens, your hook will have isError: true but no network request will be made. The error property of your hook will be a SerializedError object with properties name, message and stack, which you can use to display the error in your UI.
This is the same type of error object that you get if you have a TypeError somewhere in your code. Note that JavaScript errors will have error.message while API errors (FetchBaseQueryError) will have error.error.
const Category = ({ name }) => {
const { data, error, isError } = useGetSubCategoriesQuery(name);
return (
<div>
<h3>Name: "{name}"</h3>
{isError && (
<div>{error?.error ?? error?.message}</div>
)}
</div>
);
};
CodeSandbox Link

facebook messenger bot encoding error

I have written sample echo message bot using facebook messenger api and wit.ai actions.
My message from facebook page is received and the proper action function defined using wit api's is also getting called. However
while returning the response, i am getting followin error as -
Oops! An error occurred while forwarding the response to : Error: (#100) Param message[text] must be a UTF-8 encoded string
at fetch.then.then.json (/app/index.js:106:13)
at process._tickCallback (internal/process/next_tick.js:103:7)
Here is the function which is used to return the response -
const fbMessage = (id, text) => {
const body = JSON.stringify({
recipient: { id },
message: { text },
});
const qs = 'access_token=' + encodeURIComponent(FB_PAGE_ACCESS_TOKEN);
return fetch('https://graph.facebook.com/v2.6/me/messages?' + qs, {
method: 'POST',
headers: {'Content-Type': 'application/json; charset=UTF-8'},
body
})
.then(rsp => rsp.json())
.then(json => {
if (json.error && json.error.message) {
throw new Error(json.error.message);`enter code here`
}
return json;
});
};
I have copied this function from the messenger.js file from the documentation since i am just trying the POC.
I checked the values for text and id in this function and verified using console.log statements and those are coming properly.
Can some experts help me to solve this error?
Note - I tried encoding the text using text.toString("utf8"); but it returns the encoding string as [object object] and thats the
response i get from bot. so it doesnt work.
Get the latest code from node-wit, there is a change in facebook id usage,
According to Facebook:
On Tue May 17 format of user and page ids delivered via webhooks will
change from an int to a string to better support default json encoder
in js (that trims long ints). Please make sure your app works with
string ids returned from webhooks as well as with ints.
Still you are getting issue with the api try to add if(event.message && !event.message.is_echo) condition as shown in below code.
// Message handler
app.post('/webhook', (req, res) => {
const data = req.body;
if (data.object === 'page') {
data.entry.forEach(entry => {
entry.messaging.forEach(event => {
if (event.message && !event.message.is_echo) {
const sender = event.sender.id;
const sessionId = findOrCreateSession(sender);
const {text, attachments} = event.message;
if (attachments) {
fbMessage(sender, 'Sorry I can only process text messages for now.')
.catch(console.error);
} else if (text) {
wit.runActions(
sessionId, // the user's current session
text, // the user's message
sessions[sessionId].context // the user's current session state
).then((context) => {
console.log('Waiting for next user messages');
sessions[sessionId].context = context;
})
.catch((err) => {
console.error('Oops! Got an error from Wit: ', err.stack || err);
})
}
} else {
console.log('received event', JSON.stringify(event));
}
});
});
}
res.sendStatus(200);
});
Reference:
no matching user bug
no matching user fix

Facebook batch calls with JSONP

As of 10.04.2012,
There is a short paragraph in the Facebook developer document for 'batch request' entitled: Batch calls with JSONP, which reads:
"The Batch API supports JSONP, just like the rest of the Graph API -
the JSONP callback function is specified using the 'callback' query string
or form post parameter."
I thought that meant you can also do a batch request using JSONP from Javascript (which will be a GET request, as JSONP works only as a GET request), so I tried that, with adding a 'batch' parameter (containing objects describing requests for batch as in the doc) to the query string. Response from FB server was:
Only POST is allowed for batch requests
So, questions:
1. What did they mean in that paragraph?
2. Is there a way to do an asynchronous batch request from Javascript?
I get the same. Sample code is
jQuery.support.cors = true;
var AjaxRequest = jQuery.ajax( {
url: "http://graph.facebook.com/",
type: "POST",
contentType: "application/x-www-form-urlencoded",
data: { "access_token": AccessToken, "batch": BatchRequest },
dataType: "jsonp",
error: function( jqXHR, textStatus, errorThrown ) {
... show error stuff
},
success: function( Return, textStatus, jqXHR ) {
showLog( "Return " + JSON.stringify( Return ) );
showLog( "textStatus " + textStatus );
showLog( "jqXHR " + JSON.stringify( jqXHR ) );
if ( Return.error ) {
... go away
}
else {
... use the data
}
}
} ); // eo ajax request
which gives
Return {"error":3,"error_description":"Only POST is allowed for batch requests"}
textStatus success
jqXHR {"readyState":4,"status":200,"statusText":"success"}
i.e. it successfully sends back an error message. JSONP translates the POST type to a GET, which Facebook doesn't support...
To answer qu.2 you can use FB.api to do asynchronous batch request in javascript. I was trying out JSONP because IE8 keeps hanging on the return from Facebook with FB.api.