I have searched and searched trying to find the answer to this but from all the examples and answers I've read I can't see what my problem is.
I am trying to update the extended properties of a series of events selected by a user. The IDs of the calendar events (from the Advanced API, not the built in CalendarApp) are stored in an array as they're selected. I'm then passing this array to a function to be looped through and update the extended properties of each event identified in the array.
It simply doesn't work, I just get null returned from the patch call, not even an error that I could work with. Here is a screenshot of logged output, the null at the end if what the patch request returns.
My function is:
function updateLessonsStatus(arrCalIds){
try {
Logger.log(arrCalIds);
arrCalIds.forEach(function(row){
Logger.log(row);
var objEventPatch = {
"resource": {
"extendedProperties": {
"shared": {
"status": "accounted"
}
}
}
};
Logger.log(objEventPatch);
return Calendar.Events.patch(objEventPatch, "primary", row);
//return true;
});
}
catch(err) {
Logger.log(err);
throw err;
}
}
I have also tried setting objEventPatch like this as per Google's Calendar API patch 'Try this API' reference https://developers.google.com/calendar/v3/reference/events/patch :
var objEventPatch = {
"calendarId": "primary",
"eventId": row,
"resource": {
"extendedProperties": {
"shared": {
"status": "accounted"
}
}
}
};
I still get null from Google Apps Script. I can succesfully get and patch events using the IDs I have using the 'Try this API' feature.
There are very few examples of using the advanced APIs with Google Apps Script in Google's documentation and nothing I could find for patch so I have used the Javascript examples to construct what I have written so far.
Can anybody help with what I am doing wrong?
(UPDATED for clarity and included image of null returned logger output)
You are providing one nested object too much
Modify
var objEventPatch = {
"resource": {
"extendedProperties": {
"shared": {
"status": "accounteddd"
}
}
}
};
to
var objEventPatch = {
"extendedProperties": {
"shared": {
"status": "accounteddd"
}
}
};
Side note:
If you want to explore the request response for troubleshooting purposes, I recommend you to perform your request with a call to the request URL with the UrlFetchApp instead of using the prebuilt Calendar service.
Related
I am trying to execute a Report with the Google Analytics Data API. I built the request using Google's documentation and I get this script. The script works well if I execute it directly with the "Try this method" option in the documentation:
<script src="https://apis.google.com/js/api.js"></script>
<script>
/**
* Sample JavaScript code for analyticsdata.properties.runReport
* See instructions for running APIs Explorer code samples locally:
* https://developers.google.com/explorer-help/code-samples#javascript
*/
function authenticate() {
return gapi.auth2.getAuthInstance()
.signIn({scope: "https://www.googleapis.com/auth/analytics https://www.googleapis.com/auth/analytics.readonly"})
.then(function() { console.log("Sign-in successful"); },
function(err) { console.error("Error signing in", err); });
}
function loadClient() {
gapi.client.setApiKey("YOUR_API_KEY");
return gapi.client.load("https://analyticsdata.googleapis.com/$discovery/rest?version=v1beta")
.then(function() { console.log("GAPI client loaded for API"); },
function(err) { console.error("Error loading GAPI client for API", err); });
}
// Make sure the client is loaded and sign-in is complete before calling this method.
function execute() {
return gapi.client.analyticsdata.properties.runReport({
"property": "properties/295880876",
"resource": {
"metrics": [
{
"name": "sessions"
},
{
"name": "conversions"
},
{
"name": "totalRevenue"
}
],
"dimensions": [
{
"name": "week"
},
{
"name": "year"
}
],
"dateRanges": [
{
"startDate": "2021-01-01",
"endDate": "today"
}
]
}
})
.then(function(response) {
// Handle the results here (response.result has the parsed body).
console.log("Response", response);
},
function(err) { console.error("Execute error", err); });
}
gapi.load("client:auth2", function() {
gapi.auth2.init({client_id: "YOUR_CLIENT_ID"});
});
</script>
<button onclick="authenticate().then(loadClient)">authorize and load</button>
<button onclick="execute()">execute</button>
Now I want to run this Script in Apps Script and import the Data to a spreadsheet. However as this is a HTML, if I want to run it as a JS and delete the script tags and content I receive "gapi is not defined".
It is clear that I still have to load https://apis.google.com/js/api.js somehow, but how?
Thanks for your help!
I believe your goal is as follows.
You want to use "Method: properties.runReport" with Google Apps Script.
When I saw your showing script, it seems that it is used for Javascript. In this case, Javascript is different from Google Apps Script. I think that this might be the reason for your issue.
In order to achieve your goal, in the current stage, Advanced Google services can be used. So, in this answer, I would like to propose using AnalyticsData with the Advanced Google services of Google Apps Script.
The sample script is as follows.
Sample script:
Please copy and paste the following script to the script editor of Google Spreadsheet. And, please enable "AnalyticsData" at Advanced Google services. And, please set your property ID to ### of const property = "properties/###";.
function myFunction() {
// Retrieve values from Google Analytics Data API (GA4)
const property = "properties/###"; // Please set your property ID.
const resource = {
"metrics": [
{
"name": "sessions"
},
{
"name": "conversions"
},
{
"name": "totalRevenue"
}
],
"dimensions": [
{
"name": "week"
},
{
"name": "year"
}
],
"dateRanges": [
{
"startDate": "2021-01-01",
"endDate": "today"
}
]
};
const obj = AnalyticsData.Properties.runReport(resource, property);
// Put values to Spreadsheet.
const header = [...obj.dimensionHeaders.map(({ name }) => name), ...obj.metricHeaders.map(({ name }) => name)];
const values = [header, ...obj.rows.map(({ dimensionValues, metricValues }) => [...dimensionValues.map(({ value }) => value), ...metricValues.map(({ value }) => value)])];
const sheetName = "Sheet1"; // Please set the sheet name.
const sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(sheetName)
sheet.getRange(1, 1, values.length, values[0].length).setValues(values);
}
When you run this script, the values are retrieved from "properties.runReport", and the retrieved values are put into the Spreadsheet.
Note:
I cannot know the final result you expect from Now I want to run this Script in Apps Script and import the Data to a spreadsheet.. So, in the above sample script, the retrieved values are put to "Sheet1" as the header of week,year,sessions,conversions,totalRevenue. If you want to change this, please modify this for your actual situation.
Reference:
Method: properties.runReport
My Code looks like this :-
var vision = require('#google-cloud/vision');
handleSubmit = () =>{
console.log("encoded string submitted=",this.state.files);
this.useVisionCloud();
}
useVisionCloud = () =>{
const client = new vision.ImageAnnotatorClient();
const request_body = {
"requests": [
{
"image": {
"content": this.state.files
},
"features": [
{
"type": "TEXT_DETECTION"
}
]
}
]
};
client.textDetection(request_body).then(response => {
console.log("text got=",response);
// doThingsWith(response);
})
.catch(err => {
console.log("error got=",err);
});
}
I already tried setting environment variable but didn't work .
I have also created service account and downloaded the file.json
but dont know how to use it for authentication
im getting the following error :-
Uncaught Error: {"clientConfig":{},"port":443,"servicePath":"vision.googleapis.com","scopes":["https://www.googleapis.com/auth/cloud-platform","https://www.googleapis.com/auth/cloud-vision"]}You need to pass auth instance to use gRPC-fallback client in browser. Use OAuth2Client from google-auth-library.
on triggering a post request to Google API .
Final Query is :- I am not able to understand how to authenticate API so that i can further use it to detect text in my images
Set the env variable eg:
export GOOGLE_APPLICATION_CREDENTIALS="[PATH]"
I would recommend having a separate backend that calls vision api. Then have the javascript code in your browser call your backend.
Background: What I am trying to achieve is to delete multiple values from elastic using a single API call. Our app uses Node-Red to create the backend API's.
I am using below curl command to delete multiple doc id's and it is working like a charm. It deletes the docs found with id's xxxxx and yyyyy.
POST /tom-access/doc/_delete_by_query
{
"query": {
"terms": {
"_id": [
"xxxxx",
"yyyyy"
]
}
}
}
However, when I try to do the same via Node-Red (using a JavaScript function), I am getting below error.
{"error":{"root_cause":[{"type":"action_request_validation_exception","reason":"Validation
Failed: 1: query is
missing;"}],"type":"action_request_validation_exception","reason":"Validation
Failed: 1: query is missing;"},"status":400}
Here is what I have inside the Node-Red JavaScript function:
if (!msg.headers) msg.headers = {};
msg.req = {
"query": {
"terms": {
"id": [
"xxxxx",
"yyyyy"
]
}
}
};
msg.headers = {
"Content-Type": "application/json",
"Authorization" : "Basic xxxxxxxxxxxxxxxxxxxxx"
};
msg.method = "POST"
// New elastic
msg.url = "http://elastic.test.com/tom-access/doc/_delete_by_query";
return msg;
The next node makes an HTTP CALL using above msg object but results in the error mentioned above. I am new to Node-Red, JavaScript and Elastic as well. HEEELP!!!
The endpoint is probably expecting the query to be in the body of the requests.
You should be setting it under msg.payload not msg.req.
I am attempting to get a list out of my database. The documents look like:
{
"class": "lists",
"collection": "symptoms",
"order": "6",
"en": "Headache",
"_id": "9022034e7d5ecd0efab0762c5b7f0c04"
}
There are an arbitrary number of "collection"s.
A view function simply returns a bunch of objects in the class "lists":
// Emit lists
exports.viewlist = {
map: function(doc) {
if (doc.class === 'lists') {
emit(
doc.collection, {
order: doc.order,
name: doc.en
});
}
}
};
I wrote a list function to try to filter the output to just the list that I want.
exports.viewlist = function(head, req) {
var row;
start({
code: 200,
headers: {
'Content-Type': 'text/json; charset=utf-8',
}
});
while (row = getRow()) {
if (row.collection === req.l) {
send(JSON.stringify(row.value));
}
}
};
CouchDB throws an error when I visit the URL of the list:
http://localhost:5984/dev/_design/emr/_list/viewlists/viewlist?l=symptoms
{"error":"TypeError","reason":"{[{<<\"message\">>,<<\"point is undefined\">>},
{<<\"fileName\">>,<<\"/usr/share/couchdb/server/main.js\">>},
{<<\"lineNumber\">>,1500},\n {<<\"stack\">>,
<<\"(\\\"_design/emr\\\",[object Array],
[object Array])#/usr/share/couchdb/server/main.js:1500\
()#/usr/share/couchdb/server/main.js:1562\
#/usr/share/couchdb/server/main.js:1573\
\">>}]}"}
I can't figure out where I'm going wrong here.
I also ran into this error and what causes it, as hinted at by #Pea-pod here Submitting form to couchDB through update handler not working, is not defining properly your exports in the couchapp's design documents. In our case it was as list function that couldn't be called and instead displayed a 500 error with Type error and point is undefined in the couchdb log.
We use kanso and in the app.js we hadn't required the list file. We had:
module.exports = {
rewrites: require('./rewrites'),
views: require('./views'),
shows: require('./shows')
};
Changing it to the following solved the problem:
module.exports = {
rewrites: require('./rewrites'),
views: require('./views'),
shows: require('./shows')
lists: require('./lists'),
};
Can I suggest to a moderator to change the title of this question to include point is undefined which is the error that shows up in the CouchDB log when this type of error is made, in order to help others find it more easily?
The problem may be with the actual client, but he's not responding on github, so I'll give this a shot!
I'm trying to post, in the body, nested JSON:
{
"rowkeys":[
{
"rowkey":"rk",
"columns":[
{
"columnname":"cn",
"columnvalue":"{\"date\":\"2011-06-21T00:53:10.309Z\",\"disk0\":{\"kbt\":31.55,\"tps\":6,\"mbs\":0.17},\"cpu\":{\"us\":5,\"sy\":4,\"id\":90},\"load_average\":{\"m1\":0.85,\"m5\":0.86,\"m15\":0.78}}",
"ttl":10000
},
{
"columnname":"cn",
"columnvalue":"cv",
"ttl":10000
}
]
},
{
"rowkey":"rk",
"columns":[
{
"columnname":"cn",
"columnvalue":"fd"
},
{
"columnname":"cn",
"columnvalue":"cv"
}
]
}
]
}
When I remove the columnvalue's json string, the POST works. Maybe there's something I'm missing regarding escaping? I've tried a few built in escape utilities to no avail.
var jsonString='the json string above here';
var sys = require('sys'),
rest = require('fermata'), // https://github.com/andyet/fermata
stack = require('long-stack-traces');
var token = ''; // Username
var accountId = ''; // Password
var api = rest.api({
url : 'http://url/v0.1/',
user : token,
password : accountId
});
var postParams = {
body: jsonString
};
(api(postParams)).post(function (error, result) {
if (error)
sys.puts(error);
sys.puts(result);
});
The API I'm posting to can't deserialize this.
{
"rowkeys":[
{
"rowkey":"rk",
"columns":[
{
"columnname":"cn",
"columnvalue":{
"date":"2011-06-21T00:53:10.309Z",
"disk0":{
"kbt":31.55,
"tps":6,
"mbs":0.17
},
"cpu":{
"us":5,
"sy":4,
"id":90
},
"load_average":{
"m1":0.85,
"m5":0.86,
"m15":0.78
}
},
"ttl":10000
},
{
"columnname":"cn",
"columnvalue":"cv",
"ttl":10000
}
]
},
{
"rowkey":"rk",
"columns":[
{
"columnname":"cn",
"columnvalue":"fd"
},
{
"columnname":"cn",
"columnvalue":"cv"
}
]
}
]
}
Dual problems occuring at the same occurred led me to find an issue with the fermata library handling large JSON posts. The JSON above is just fine!
I think the real problem here is that you are trying to post data via a URL parameter instead of via the request body.
You are using Fermata like this:
path = fermata.api({url:"http://example.com/path");
data = {key1:"value1", key2:"value2"};
path(data).post(callback);
What path(data) represents is still a URL, with data showing up in the query part. So your code is posting to "http://example.com/path/endpoint?key1=value1&key2=value2" with an empty body.
Since your data is large, I'm not surprised if your web server would look at such a long URL and send back a 400 instead. Assuming your API can also handle JSON data in the POST body, a better way to send a large amount of data would be to use Fermata like this instead:
path = fermata.api({url:"http://example.com/path");
data = {key1:"value1", key2:"value2"};
path.post(data, callback);
This will post your data as a JSON string to "http://example.com/path" and you would be a lot less likely to run into data size problems.
Hope this helps! The "magic" of Fermata is that unless you pass a callback function, you are getting local URL representations, instead of calling HTTP functions on them.