im trying to access the calendar resources data in the Google Apps domain.
I have this:
function myFunction() {
var url = 'https://apps-apis.google.com/a/feeds/calendar/resource/2.0/example.com/';
var response = UrlFetchApp.fetch(url);
Logger.log(response);
}
But i need to authorize.
"Request failed for https://apps-apis.google.com/a/feeds/calendar/resource/2.0/example.com/ returned code 401. Authorization required "
Does someone know how i Authorize? I tried to add the advances services and Calendar API, but didn't work.
Why don't you use Calendar Service in Google Apps Script. It allows you to interact with Calendar Objects and Events without worrying for oAuth.
e.g to Fetch Events in Calendar
function fetchEVents() {
var d1 = new Date("4/26/2013");
var d2 = new Date("4/26/2014");
var events = CalendarApp.openByName("myCalendarName").getEvents(d1, d2);
if (events.length > 0) { // Log the time of first event
Logger.log(events[0].getStartTime() + " : " + events[0].getEndTime());
}
}
For more details, you may refer to the following resources.
https://developers.google.com/apps-script/reference/calendar/
https://developers.google.com/apps-script/articles/sites_tutorial#section2
Related
I used Directory API push notifications example of https://stackoverflow.com/users/6586255/dimu-designs from this question: Is it possible to watch Directory API changes from Google App Maker/Google Apps Script?
I have two projects setup, another one is webhook itself:
/** HTTP GET request handler */
function doGet(e) {
return ContentService.createTextOutput("GET message");
}
/** HTTP POST request handler */
function doPost(e) {
return ContentService.createTextOutput("POST message");
}
And other one is the watch request:
function startUpdateWatch() {
var channel = AdminDirectory.newChannel(),
receivingURL = "https://script.google.com/macros/s/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx/exec",
gSuiteDomain = "[business-name].com",
event = "update";
channel.id = Utilities.getUuid();
channel.type = "web_hook";
channel.address = receivingURL + "?domain=" + gSuiteDomain + "&event=" + event;
channel.expiration = Date.now() + 21600000; // max of 6 hours in the future; Note: watch must be renew before expiration to keep sending notifications
AdminDirectory.Users.watch(
channel,
{
"domain":gSuiteDomain,
"event":event
}
);
}
Webhook url works fine, it fires "Get" when I try to open it via browser. startUpdateWatch function starts fine as well without errors and if I try to change the url to something else, I get an error, so that receiving url should be ok as well.
How you debug that push channel? I have tried to launch function with different events like 'add' and 'delete' as well and then deleted/added/modified user in G suite, but no push from that function towards the url.
I am trying to "install" a Google script as a menu item in a Google Site (a new Google Site--not the "Classic Google Site").
This script is supposed to add a new line to a spreadsheet that is embedded in the Site. That spreadsheet (named "Catalog") is a Google Sheet and the script (I want to run from the Google Site) is already installed as a bound script in the Sheet and works when toggled from the S
heet.
The script essentially adds a new line at the bottom of my song catalog to create a new line to add a new song.
The script that is working in the spreadsheet is:
function addSong() {
var ss = SpreadsheetApp.getActive();
var sheet = ss.getActiveSheet();
var numRows = sheet.getLastRow()
sheet.appendRow([numRows+1]);
}
My problem is I do not know how to access the script from the site. I.e., I do not know how to reference the script in the site menu (by URL or what?) to get it to run.
The way I envision it working is that I have a sub-page under my "Catalog" menu in the site called "Add Song" and when I toggle it, I want the script to run and add a line to the Catalog Sheet.
Any help?
Updated with a cleaner example:
Firstly, the best way to access your GAS script from elsewhere is probably to publish it as a Web App. That way the script can be called via its published URL. The main requirement for a Web App is that it has a doGet() function as an entry point.
I'm pretty sure that you can only associate a new Google Sites menu item with another page within the same site. So you can’t invoke the WebApp (via it's URL) directly from a menu. But on that new Sites page the menu item takes you to, you can either:
associate a Sites button with the Web App URL (if that helps), or
embed some HTML code with JavaScript in the page that is invoked when the page is loaded; a bit more complicated, but it does mean the call to the Web App would be automated.
The code below is a simple web app, which is a bound function within a sheet. If you publish this (Publish >> Deploy as a WebApp...) and then grab the url you can associate this with a button or call from the page.
function doGet(request){
addSong(request.parameter.song); // Call your own function.
var response = {status: "SUCCESS", data: request.parameter.song};
// Return the response.
return ContentService.createTextOutput(JSON.stringify(response)).setMimeType(ContentService.MimeType.JSON);
}
function addSong(song) {
var ss = SpreadsheetApp.getActive();
var sheet = ss.getActiveSheet();
var numRows = sheet.getLastRow()
sheet.appendRow([numRows+1,song]);
}
To use a button add the following as a link with the button:
https://script.google.com/macros/s/<your web app ref>/exec?song=%22Bohemian%20Rhapsody%22
The code below is an example of automatically calling the WebApp from embedded HTML in the Sites web page accessed via the menu. There are other ways of invoking the Web App from JavaScript, but XMLHttpRequest() works with most browsers.
<!DOCTYPE html>
<html>
<body onload="test('https://script.google.com/macros/s/<your web app ref>/exec?song=StairwaytoHeaven') ;">
<p id="message">? </p>
<script>
function test(url) {
var XHR = new XMLHttpRequest();
XHR.onreadystatechange = function() {
if(XHR.readyState == 4) {
if(XHR.status == 200) {
console.log("SUCCESS: status = "+XHR.status);
document.getElementById("message").innerHTML = XHR.responseText;
console.log(XHR.responseText);
} else {
console.log("FAILURE: status = "+XHR.readystate+" "+XHR.status);
document.getElementById("message").innerHTML = "Failure";
}
}
}
XHR.open("GET", url + ((/\?/).test(url) ? "&" : "?") + Date.now()); // Add timestamp to disable caching, if required.
XHR.send();
return;
}
</script>
</body>
</html>
Does anyone know if something has changed in the NYT API access, or how to reroute access to the API so that the connection is successful?
For my MFA thesis a couple years ago, I was scripting NYT API data into InDesign, using the Extendables library, and it worked great to call the necessary API URL. Now, after some time not using the scripts I'd written, the "http.get()" no longer seems to make the connection, and I receive an error from the Extendables "index.jsx" (from within the "core-packages/http/lib" file structure) and the "this.process_headers = function () {" which highlights "this.status = raw_head[0].split(' ')[1].to('int');" which returns "undefined is not an object" in ESTK.
A snippet of my code is:
var article_callURL = String(ny_article_search_baseURL + "&begin_date=" + begin_date + "&end_date=" + end_date + "&page=" + offset + sort_oldest + ny_article_key);
$.writeln(article_callURL);
//==Using extendables.jsx
var http = require("http");
var article_response = http.get(article_callURL);
if (article_response.status_code == 200) {
$.writeln(article_response.body);
} else {
$.writeln("Connection failed");
}
ESTK will write the article_callURL, but never gets passed the
var http = require("http");
code. If someone could help me resolve this, it'd be greatly appreciated.
For SharePoint 2013, is there any way to log to the ULS using the JSOM?
If possible I would like to avoid doing things like writing a custom handler that can be called with ajax.
SharePoint provides a web service named SharePoint Diagnostics (diagnostics.asmx), this web service enables a client application to submit diagnostic reports directly to the ULS logs, follow Writing to the SharePoint Unified Logging Service from JavaScript for a more details.
SharePoint JavaScript library (init.js) contains the following functions that consume Diagnostics web service:
function ULSOnError(msg, url, line) {
return ULSSendExceptionImpl(msg, url, line, ULSOnError.caller);
}
function ULSSendException(ex) {
var message = ex.message;
if (typeof message == "undefined")
message = ex.toString();
ULSSendExceptionImpl(message, location.href, 0, ULSSendException.caller);
}
Example
var ctx = SP.ClientContext.get_current();
var list = ctx.get_web().get_lists().getByTitle(listTitle);
ctx.load(list);
ctx.executeQueryAsync(function() {
//...
},
function(sender,args){
ULS.enable = true; //ensure ULS logging is enabled
ULSOnError('An error occured while getting list' + args.get_message(), location.href, 0);
});
I would like to create Gmail filters programmatically in a Chrome extension for standard Gmail users (read non Google App). Currently, thanks to those 2 (outdated) resources:
Grexit Filters API
Gmail Filter Assistant, Userscript
I have managed to develop an early prototype able to create a filter which automatically archives ("cf2_ar=true") emails received at a certain email address ("cf1_to="). However, it seems like any other "cf2" parameters used by Gmail are not valid anymore. For instance, applying a label with parameters "cf2_cat=" or "cf2_sel=" does nothing.
I know that Gmail's code is not very friendly and open when it comes to app or extension development but I would appreciate any help if some of you have any ideas, suggestions or updates regarding the current parameters used by Gmail to create filters, especially the one(s) used to apply labels to messages.
script.js (DOM end)
// Inject API into Gmail DOM
var s = document.createElement('script');
s.src = chrome.runtime.getURL('js/lib/api.js');
(document.head||document.documentElement).appendChild(s);
s.onload = function() {
s.parentNode.removeChild(s);
};
document.addEventListener('Demo_connectExtension', function(e) {
if(e.detail) {
// Gmail GLOBALS : DATA
DATA = e.detail;
user_data[0] = DATA[9]; // Id (ik)
user_data[1] = DATA[10]; // Email
user_data[2] = DATA[17][9][8]; // Locale
user_data[3] = DATA[7]; // Gmail inbox
var emailarr = user_data[1].split('#');
user_data[4] = emailarr[0] + '+do#' + emailarr[1]; // email for filter
var regex_cookie = new RegExp("GMAIL_AT=(.+?);");
if (typeof document.cookie !== 'undefined') {
// Get cookie
var gmcookie = document.cookie.match(regex_cookie)[1];
console.log('cookie:' + gmcookie);
var gmail_filter_url = 'https://mail.google.com' + user_data[3] +
'/?ui=2&ik=' + user_data[0] +
'&at=' + gmcookie +
'&view=up&act=cf&pcd=1&mb=0&rt=c';
var postdata = 'search=cf&cf1_to=' +
encodeURIComponent(user_data[4]) +
'&cf2_ar=true';
$.post(gmail_filter_url, postdata, function(gmail_response){
console.log(gmail_response);
});
}
// [...]
api.js (injected into Gmail)
'use strict';
var GLOBALS;
setTimeout(function() {
/* Send Gmail Data to my extension */
document.dispatchEvent(
new CustomEvent('Demo_connectExtension', {
detail: GLOBALS
}));
}, 1);
Actually, cf2_sel parameter does work for me. I had somewhat similar issue, described in this question and answer.
My code uses Grexit filters project and solves a sample use case:
"When a keyword is present in email content, add label, archive and set filter for this keyword"
I tested it successfully and when looking at Grexit code, 'labelas' action sets abovementioned "cf2_sel" parameter.
My sample project can be found here and provide you with means for quick testing and verification if this works for you.