I'm not very experienced with javascript, but the google sheets API is driving me crazy. Took forever to get it to call a range, and now I can't get it to append or update the sheet.
I have done everything in the API setup, I have my API key, client ID, access tokens, all of that, but I can't figure out how to successfully POST to my sheet, and my code is now spaghetti from trying.
Here's what I'm trying to do: I have a button, where onclick it appends a range with the current date, but doing so returns a 401 error, meaning I don't have active credentials. However, I'm signed in, I've tried about 10 different ways of providing the token, and can't update the sheet. here's what I currently have for the onclick function:
CODE EDITED FROM ORIGINAL POST
function fv1Passivated() {
let values = [
[
currentDate
],
];
values = values;
const body = {
values: values,
};
try {
gapi.client.sheets.spreadsheets.values.append({
spreadsheetId: SHEET_ID,
range: 'FV1!A2:A',
valueInputOption: 'USER_ENTERED',
resource: body,
}).then(function() {
gapi.auth2.getAuthInstance().isSignedIn.listen(updateSignInStatus);
updateSignInStatus(gapi.auth2.getAuthInstance().isSignedIn.get());
}).then((response) => {
var result = response.result;
console.log(`${result.updates.updatedCells} cells appended.`);
if (callback) callback(response);
});
} catch (err) {
console.log(err.message);
return;
}
};
And I have no idea how to even start untangling this into something that appends the current date to the end of the range. I'm going a little crazy, as I'm only halfway through freecodecamp's javascript module. Can anyone help? This question is on here a bunch, where people state the need for OAuth over api key, but with zero explanation on how to do that and it's breaking my newbie brain trying to figure it out.
Tried the google api's documentation for a simple write command. Expected it to work, but here we are. Error 401 returned in browser when launching it against localhost.
Related
I am getting the following error when trying to write to Firestore. This is done in JavaScript(React).Can anyone tell what is this and how can I fix this?
#firebase/firestore: Firestore (8.3.1): RestConnection Commit failed with error: {"code":"failed-precondition","name":"FirebaseError"} url: https://firestore.googleapis.com/v1/projects/{project name}/databases/(default)/documents:commit request: {"writes":[{"update":{"name":"projects/{project name}/databases/(default)/documents/teams/T22yKl1ERQSlfuZNitrvs2vRjSJ2/team-analytics/T22yKl1ERQSlfuZNitrvs2vRjSJ2-Dec-22-2021","fields":{"homePageViews":{"integerValue":"3"},"timeModified":{"timestampValue":"2021-12-22T09:32:00.000000000Z"}}},"updateMask":{"fieldPaths":["homePageViews","timeModified"]},"currentDocument":{"updateTime":"2021-12-22T09:23:08.916511000Z"}}]}
My code that is trying to access Firestore is shown below:
return db.runTransaction(async (transaction) => {
const analyticsDoc = await transaction.get(analyticsReference);
if (analyticsDoc.exists) {
const analytics: any = analyticsDoc.data();
return transaction.update(analyticsReference, { homePageViews: analytics.homePageViews + 1, timeModified: getCurrentDateTime() });
}
const newAnalytics: AnalyticsObject = {
totalViews: 0,
homePageViews: 1,
timeModified: getCurrentDateTime(),
};
return transaction.set(analyticsReference, newAnalytics);
});
I am also getting the following error in my console:
POST https://firestore.googleapis.com/v1/projects/optimx-sports/databases/(default)/documents:commit 400
Edit: After more digging in, I am thinking it might be because I am sending 2 transactions to the same document simultaneously. Is it possible that this error is because of this?
Below are a few Points you can check with:
In Cloud Firestore, you can only update a single document about once
per second, which might be too low for some high-traffic
applications. Have a look at Firestore documentation.
You can refer to the Documentation.
Also You can try with Postman API to access data.
Another way is combining two commits as well.
The issue was that I was sending two transaction commits to one firestore document within a second. The second commit was raising the above error. Fixed it by combining the two commits
Azure is driving me mad again. What I try to achieve is that the data that comes in through an Event Hub needs to be written to the database. What I got working thus far is that the data arrives at the Event Hub and that the Azure function is able to post data to the database. I would prefer to do this with Node.JS as the integration seems kind of nice in Azure. The script I use to send some bogus data to the database is as follows:
module.exports = async function (context, eventHubMessages){
const initOptions = {
query(e) {context.log(e.query)},
capSQL: true
//capSQL: true // capitalize all generated SQL
};
const pgp = require('pg-promise')(initOptions);
const db = pgp({
host: '####',
user: '####',
password: '####',
database: 'iotdemo',
port: 5432,
ssl: true
});
// our set of columns, to be created only once (statically), and then reused,
// to let it cache up its formatting templates for high performance:
const cs = new pgp.helpers.ColumnSet(['customer', 'tag', 'value', 'period'], {table: 'testtable'});
// generating a multi-row insert query:
const query = pgp.helpers.insert(JSON.parse(eventHubMessages), cs);
//=> INSERT INTO "tmp"("col_a","col_b") VALUES('a1','b1'),('a2','b2')
// executing the query:
db.none(query);
};
And yes, this is a snippet from somewhere else. The 'eventHubMessages' should contain the payload. A couple of issues that I have had thus far are:
I can send a payload defined within the script or whilst giving it a testing payload, but I cant send the payload of the actual message
pg-promise returns a 202 regardless of whether it fails or not, so debugging is 'blind' at the moment. Any tips on how to get proper logging would be much appreciated.
I used 'capture events' in the event hub instance to capture the actual messages. These were stored in a blob storage. In noticed that the format is Avro. Do I need to peel away at that object to get to the actual array?
The input should look something like this:
[{"customer": duderino, "tag": nice_rug, "value": 10, "period": 163249839}]
I think I have 2 issues:
I dont know how to get meaningful logging out of the Azure function using Node.JS
Something is off about how my payload is coming in.
A more deeper question is, how do I know whether the Azure function is getting the data that it should. I know that the Event Grid gets the data, but there is no throughput. Namespaces are consistent and the Azure Function should be triggered by that namespace and get the input as a string.
I am seriously lost and out of my depth. Apart from the solution I would also appreciate feedback on my request. I am not a pro on StackOverflow and don't want to waste your time.
Regards
Ok, so after some digging I found a few things to resolve the issue. First of all, I was receiving the payload as a string, meaning that I needed it to parse first, before I could make it a callable object. In terms of code its simple, and part of the base functions of node.js
var parsed_payload = JSON.parse(payload_that_is_a_string);
Lastly, to get meaningful logging I found that the PG-Promise module has great support for that, and that this can be configured when loading the module itself. I was particularly interested in errors, so I enabled that option like so:
const initOptions = {
query(e) {console.log(e.query)},
capSQL: true,
//capSQL: true // capitalize all generated SQL
error: function (error, e) {
if (e.cn) {
// A connection-related error;
// console.log("DC:", e.cn);
// console.log("EVENT:", error.message);
}
}
};
That then can be used as a settings object for loading PG-Promise:
const pgp = require('pg-promise')(initOptions);
Thanks for considering my ask for help. I hope this proves useful for anyone out there!
Regards Pieter
I'm new to the javascript world and have been tinkering with Actions on Google. I had an action that was previously running but after attempting to simplify my code, I've been running into a new error I cannot seem to figure out. The code is supposed to make a call to a database and return information to the user based on the date they have selected.
Problem:
The code is supposed to make a call to a database and return information to the user based on the date they have selected. The intent seems to break down when I call the URL using axios. When I test my function I receive the following error from the Google Cloud Platform: "Error: No response has been set. Is this being used in an async call that was not returned as a promise to the intent handler?"
app.intent('Moon', (conv, {date}) => {
// Sets date to today if none given
if (!date) {
date = new Date().toISOString();
}
// Slices date string to match date format in database
const dateSlice = date.slice(5, 9);
// Call to row in dabase for the given date
function getData() {
return axios.get(`example.com/search?Date=${dateSlice}`);
}
return getData().then(res => {
res.data.map(con => {
conv.ask(`On X date there will be a ${con.Object1}`);
});
});
});
I don't know much about Promise and await but that seems to be the issue. I'm not sure how I was able to get my code to run before without these objects. I've tried to insert a Promise object before my return but it makes the rest of the function unreachable. I also checked to see if Axios had any updates but it has not, I am on the latest version. Does the error have to do with one of the returns perhaps?
It could be related to Promises, but you seem to be handling them correctly.
The call to axios.get() is returning a Promise...
... which you are returning in getData()...
... which is returned in the 'Moon' Intent handler as part of the getData().then() block.
I suspect more that this is a logic problem. If res.data is an empty array, then there will be no calls to conv.ask(), so you end up not asking anything.
There is also a problem if res.data has more than two items. In this case, you'll generate an error because you've replied with more than two "simple" responses.
Either way - you may wish to log res and/or res.data to make sure you're getting back what you think.
I created a small sample application using VueJs and created a C# REST API to store and retrieve data in a SQL Server back end.
For testing, I created a simple web page with a form to create a "note". The note is stored by the following function, 'saveData()':
saveData()
{
let promiseStack = [];
var jsondata = JSON.stringify(this.note);
promiseStack.push(this.$http.post('REST_API/note', jsondata));
Promise.all(promiseStack).then(data =>
{
this.$http.get('REST_API/note');
this.$router.push({ name: 'viewnotes', params: { id: data[0].body.id }})
}, error =>
{
console.log(error);
});
}
I tried to use a promise to wait until the 'store' operation in the backend is complete, and issue a GET request to retrieve all notes once the promise is fulfilled.
However, the get request inside the promise doesn't return any data. If I issue the get request manually later one, I retrieve the data that was stored previously.
So I had look into the C# REST API. There are currently two functions: createNote(...), getAllNotes(...). I used a StreamWriter to log to the filesystem when these functions are called, using milisecond precision. What I see is that 'createNote' is called after 'getAllNotes'. So I suspect that the API is working correctly, but something with the way I'm using promises seems to be awfully wrong.
Maybe somebody has a hint?
UPDATE
I know that the GET request doesn't return any data by using the developer toolbar in Chromium. The response is empty
The developer toolbar in the network tab shows that the requests are submitted in the correct order, so the "POST" request is issued first
It seems I found the problem. I had a 'href' tag in my 'Save' link, which triggered an early routing. The intended 'POST' and 'GET' were fired correctly, but there was another 'GET' inbetween somewhere because of the 'href' tag in the link, even though it was empty.
I removed the tag, now it works as intended.
Recently was enabled Google + Domains API For Apps Script, I have explored some options and it seems is going to work, but in the specific case of PlusdDomains.Circles.list I don't know how to pass the second argument what is an object, I can not obtain several fields in the response, this is my code.
function getProfile() {
var userId = 'me';
var post = { maxResults: 2, fields:"title"};
var profile = PlusDomains.Circles.list(userId, post);
Logger.log('all: %s', JSON.stringify(profile));
}
this is the output,all: {"title":"Google+ List of Circles"}
if I try to get another field I don't know if this is correct, I put this:
var post = { maxResults: 2, fields:["title", "items"]};
but I get the same result:all: {"title":"Google+ List of Circles"}
If I try to get the result value for items, I get undefined. I don't how to pass the object correctly or if this is a bug in the Apps Script, somebody has idea??
I'm trying to get this working too. From the public google+ domain api docs it looks that the fields property expects a string with field names comma separated, i.e.
var post = { maxResults: 2, fields:"title,items"};
I don't seem to get the items populated (all the properties are undefined) in my google apps script. But when I use the API explorer "try it" console with OAuth2 enabled for scopes https://developers.google.com/+/domains/api/circles/list and https://developers.google.com/+/domains/api/circles/list I do see the items populated, so I'm thinking there may be an issue with my scripts authorization scopes or a bug in the google apps google+ domain service.