How to get Google calendar events shared by another owner? - google-apps-script

I am new to the calendar api and have a couple of basic questions.
I want to get all of the events, on all of the calendars, that another user, tonya123456#gmail.com has shared with me. She is the owner, not me.
"This user owns or is subscribed to 0.0 calendars" is the response when I run this code:
var calendar = CalendarApp.getCalendarsByName('tonya123456#gmail.com');
if(calendar == null){
//user may not have access, auto-subscribe them.
calendar = CalendarApp.subscribeToCalendar('tonya123456#gmail.com',
{hidden:true,selected:false});
}
Logger.log('This user owns or is subscribed to %s calendars.',
calendar.length);

One way I know of is listing all your own events that has a creator that you are looking for. The function below will grab your events and return an array of event ids that match the event creator. This isn't an inclusive solution, such as it doesn't have date ranges or handle paginated results and is just one simple way to approach this.
https://developers.google.com/google-apps/calendar/v3/reference/events/list
function getEventIdsByCreator(calendarId,creator){
return Calendar.Events.list(calendarId,{fields:"items/id,items/creator/email"})
.items.filter(function(item){
try{if(item.creator.email === creator){return true}}
catch(e){}
}).map(function(item){return item.id});
}
You would use it like:
function myFunction(){
var IDs = getEventIdsByCreator(myCalendarId,"tonya123456#gmail.com")
}

Related

Dynamic Removal of Multiple Form Options in Google Forms

I have a Google form where individuals are to enter in their employer preference and then a time for that employer. I currently have a script that is supposed to function where the form is updated to eliminate options after certain thresholds are reached. However, even when using the form with one option, it does not function correctly.
So, I have two questions here:
1) How do I get this type of action to occur in the form without utilizing the provided Google apps formLimiter and Choice Eliminator?
Here is the script code I was using:
function availableSlots()
{
var form = FormApp.openByUrl('https://docs.google.com/forms/d/e/1FAIpQLSdLRI6BmDXdCCygpHMr7o8MtnYLEVdrnumoHJfW-j_uTZCNiA/viewform?usp=sf_link');
var slots = SpreadsheetApp
.getActiveSpreadsheet()
.getRange("Sheet2!A7:C10")
.getValues();
var choice = [];
{
if (slots[s][0] != "" && slots[s][2] > 0) {
choice.push(slots[s][0]);
}
}
var formItems = form.getItems(FormApp.ItemType.LIST);
formItems[0].asListItem().setChoiceValues(choice);
}
2) Is there a way for the code to check for not only if the employer has been met by the max amount of respondents - because of all times being chosen already - and relay a message to the respondent that this employer is booked, but also behave in a way where if one time is taken for one employer, only that time is taken away if that employer was selected?

Calendar script adding guests but not sending an invite

I have a prototype script that is designed to add a guest to a calendar event. It adds them to the event just fine, but it does not trigger an invite. Could someone point me in the right direction to what's missing?
function addToEvent() {
var guest = "you#gmail.com";
var calendar = 'pbekisz#keuka.edu';
var event = "33l5k7p5qocdprt5j2c9nhbhl8";
var cal = CalendarApp.getCalendarById(calendar);
var theEvent = cal.getEventSeriesById(event);
theEvent.addGuest(guest);
}
addToEvent();
The CalendarApp documentation indicates that invitations can be sent when the event is created. Because the addGuest method does not include any indication as to how one might send the invitation, it appears that this functionality is currently limited to the time of event creation.
As a work around, you can continue with your prototype, and email your new guest(s) that they have been invited and that it should be appearing on their calendar. Alternatively, you could create a new event with your new guest(s) and send the invitation, then add the existing guests with their statuses from your original event, and then remove the original event.
Edit
As I was looking in to this further, I came across an old thread on google-apps-scripts-issues where they found the advanced Calendar API service could be used to achieve what you are trying to accomplish:
function sendInvite(calendarId, eventId, email) {
var event = Calendar.Events.get(calendarId, eventId);
event.attendees.push({
email: email
});
event = Calendar.Events.patch(event, calendarId, eventId, {
sendNotifications: true
});
}

How to stop AdWords campaign via Script?

I have MCC account which i'm using to administrate couple AdWords accounts.
I wrote Script which checking base budget of each account and then weekly check how many did they spend. Then the script subtracts these values and then every data is saved into Google Drive (spreadsheet).
Main idea behind this script was to track current budget and then warn me when some account have no more money. But then I figured out that actually i do not need to track it because AdWords script already have functions which gives possibility to stop campaign.
So i digged little bit but everything i tried is not working.
Here is extracted function (example) with i using:
function main() {
var Customer = GetAccountData("XXX-XXX-XXXX");
StopCampaigns(Customer);
if(isCampaignRuning(Customer)){
Logger.log("Campaign is runing !");
}else{
Logger.log("Campaign is STOPPED!");
}
}
/*Helper functions */
function isCampaignRuning(account){
MccApp.select(account);
var campaigns = AdWordsApp.campaigns().get();
var IsCampaignRuning = false;
while(campaigns.hasNext()) {
var campaign = campaigns.next();
if(!campaign.isPaused()){
IsCampaignRuning=true;
break;
}
}
return IsCampaignRuning;
}
function StopCampaigns(account){
MccApp.select(account);
var campaigns = AdWordsApp.campaigns().get();
while(campaigns.hasNext()) {
var campaign = campaigns.next();
if(!campaign.isPaused()){
campaign.pause();
}
}
}
function GetAccountData(id){
var childAccounts = MccApp.accounts().withIds([id]).get();
if(!childAccounts.hasNext()){
return false;
}
var childAccount = childAccounts.next();
return childAccount;
}
Here is what's happening in console:
13:08:20.974 Campaign is runing !
In changes tab:
Change for: (Here is campaign name)
New value (if run now): temporarily suspended
type of change: Update > Status
Current value: Active
How can i correctly pause campaign ?
Is there better way to track current budget of accounts ?
For anyone who will look for answer to the same problem.
There was no problem in script itself.
"if run now" - should speak itself. I was using "Preview" to run script.
In that "preview" mode script doesn't change anything in account and campaign.
It just needed to be "run" normally.

Script to validate if value exists in a list

I have a google spreadsheet which will be used for collaboration and I was able to create a UI interface which will fetch and update data from a table to make it easier for users.
For the work I need to restrict users to only be able to update rows if they are assigned to them and I am able to do it. But along with that, I also need to allow administrator to assign or update rows which are not assigned to them.
I have a table with all employee's email address and an admin flag for those who are admin.
Name____________Email________________Is Admin
Employee 1_______emp1#domain.com_____Admin
Employee 2_______emp2#domain.com_____
Employee 3_______emp3#domain.com_____
Employee 4_______emp4#domain.com_____Admin
Employee 5_______emp5#domain.com_____
Employee 6_______emp6#domain.com_____
How can I write a something in my script that will allow me to if the user who is triggering a function has admin right or not.
I user Session.getActiveUser().getEmail() to pull out the users email address. I am creating the tool to be used within google apps domain.
Code that checks if the user is the owner of the row, this part works fine but what I want to do is if a user is admin they basically will skip this check.
if (s.getRange("E4").getValue() != usr()){
msg("Once a Task is assigned to an employee, only assigned employee can make any changes to the Task. Thank you");
return;
}
s = sheet
usr() = function calling to check active user email
If I can do something like countifs where I can check count based on the email address and Admin criteria and if its >= 1 proceed if its 0 show error that you can not make changes.
Please let me know.
Really appreciate the help.
Thank you.
Zooooon
Are you looking for something like this?
function myFunction() {
var s = SpreadsheetApp.getActiveSheet();
var usr = Session.getActiveUser().getEmail();
var emails = s.getRange("E2:F").getValues();
for (var i=0;i<emails.length;i++) {
if (emails[i][0] === usr){
if (emails[i][1] === "Admin") {
//Do something when Admin
return;
} else {
//Do something when not admin
return;
}
} else {
//Do something when email not in the list
}
}
}
I am assuming your data is in the range "D:F"

Inviting guests to a "Quick Add" Google Calendar event

I am trying to improve the functionality of the "Quick Add" feature in Google Calendar. Quick Add is the feature that is normally accessed by going to Google Calendar and clicking the down arrow next to the red "Create" button (see image: http://s2.postimg.org/95zxshivt/calendar_screenshot.png).
The functionality I am trying to achieve is to allow the user to invite guests to the newly created Calendar event using keywords in what they type in the Quick Add box. For example, if the user uses the Quick Add box to add an event by entering the text Eat pizza tomorrow at 3pm with michelle#gmail.com and john#gmail.com, Google Calendar adds a new event with the title Eat pizza with michelle#gmail.com and john#gmail.com at 3pm the next day, like it is supposed to. I want to go a step further by having Google also send out two Calendar invites to the newly created event: one for michelle#gmail.com and the other to john#gmail.com.
I appreciate your advice on this topic. I am trying to understand what the best approach is:
Use a trigger with Google Apps Script to catch when the user has added a Calendar event. The trigger will access the title of the event, pick out any e-mail addresses present in the title, and send an invitation to the newly created event to each of those e-mail addresses.
Use a Chrome extension to have the user enter the string that they normally would type into the Quick Add box by clicking on the extension's icon in the Chrome browser. The extension would pick the e-mail addresses out of what the user types in, use createEventFromDescription(description) on the user's input to create the event, and then send an invitation to the newly created event to each of those e-mail addresses.
Please let me know what you think. I would greatly appreciate your ideas.
Lucy
As you probably know, there is not trigger source linked to the creation of an event from the Calendar Ui.
You have indeed 2 possibilities :
encode the event using a dedicated Ui (a chrome extension or a standalone webapp) that would take care of sending the invitations but that would probably not meet the initial requirement you described as "expanding the capabilities os the quickAdd features"
Find a way to detect an event creation and automatically send invitations from its content.
This last possibility is perfectly doable using a timer trigger that monitors your calendar and detects any new event (by comparing a list stored somewhere to the actual calendar content).
I have made such an app for a different purpose and it works nicely but there are a few difficulties you should be aware of.
When storing the events in scriptProperties (it's probably the best place to go) you have a limited amount of storage size available so you must know how much event you will be able to handle.
Any change in an event like adding a detail or rectifying a typo will re-trigger the invitation process and send the invitation again. Although this can probably be avoided but it would be quite complex.
When the script runs right after an event end, the comparison detects an change because one event is missing (from the script pov) so it could send a mail to cancel the event (if you had chosen to implement that functionality of course but I guess it's a "must have"). It might be a bit tricky to handle that situation... (compare event end time to actual time when the trigger fires the script, could be a matter of milliseconds ;-).
Apart from these difficulties, the general idea is as follow :
create a timer trigger to run every hour or so
store every event in this calendar in script Properties (or eventually in a spreadsheet) starting from the present date and ending in a few days (not too far ahead because it wouldn't make sense to send invites for an event happening next year)
compare the list with the calendar content
grab every "new" events and extract email address from the description (using regex for example or string manipulation)
send the invitations (that's the easy part)
This workflow works but it might be a bit fragile in the comparison and in the email detection.
EDIT
Since this was an interesting subject (IMHO) and that I thought I could use efficiently (now that I switched to english in my calendar UI ;-D) I wrote a code to achieve it...
I embedded the code in a spreadsheet to simplify the processsing and the storage of the events in the many calendars I own.
This spreadsheet is viewable here and if you make a copy of it you'll be able to run the code.
I setup a timer trigger that runs the autoCheckAllCal function every hour and it seems to work without any issue.
Tell me what you think.
The full code is reproduced below, it gets data from the calendar, checks if the event has guests and if not it checks the title for any valid email address (one or more) and sends the invitations automatically.
I used a regex to extract emails from the title string (this regex was borrowed from an answer on SO since I'm not good enough at this !)
note : setup an onOpen trigger for myOnOpen (because of global var declaration using SS service)
// update the ID below to your copy ID and run the Callist() function to get the calendars ID on first sheet.
//set up an onOpen trigger for the myOnOpen function
var ss = SpreadsheetApp.openById('1xDOaoSl3HbkS95cj8Jl-82rdiui7G0sFz96PIO6iVF4');// this spreadsheet
var calNamesSheet = ss.getSheetByName('calNames');
var calList = calNamesSheet.getDataRange().getValues();
function MyOnOpen() {
var menuEntries = [ {name: "Lauch autoTest", functionName: "autoCheckAllCals"},
{name: "delete created sheets", functionName: "delsheets"}
];
ss.addMenu("Tracking utilities",menuEntries);//
}
function autoCheckAllCals(){
var today = new Date(); // now
var startDate = new Date(today.setHours(0,0,0,0));// today # 0 AM
var endDate = new Date(new Date(startDate).setDate(startDate.getDate()+7)); // adjust time frame to read here = 7 days
for(var nn=0;nn<calList.length;nn++){
var logArray = new Array();
logArray.push(['Calendar + Title','Description','Start','End','Location','Creators','Date Created','Duration','Guests']);
var calName = calList[nn][0];
var calId = calList[nn][1];
var Calendar = CalendarApp.getCalendarById(calId);
var events = Calendar.getEvents(startDate , endDate);
if (events[0]) {
for (var i = 0; i < events.length; i++) {
var row = new Array();
row.push(calName +' : '+events[i].getTitle());
row.push(events[i].getDescription());
row.push(Utilities.formatDate(events[i].getStartTime(), Session.getScriptTimeZone(), "MMM-dd-yy")+' # ' +Utilities.formatDate(events[i].getStartTime(), Session.getScriptTimeZone(), "HH:mm"));
row.push(Utilities.formatDate(events[i].getEndTime(), Session.getScriptTimeZone(), "MMM-dd-yy")+' # ' +Utilities.formatDate(events[i].getEndTime(), Session.getScriptTimeZone(), "HH:mm"));
row.push(events[i].getLocation());
row.push(events[i].getCreators().join());
row.push('on '+Utilities.formatDate(events[i].getLastUpdated(), Session.getScriptTimeZone(), "MMM-dd-yyyy"));
row.push(((events[i].getEndTime() - events[i].getStartTime()) / 3600000)+' hours');//duration
var inviteList = checkInvites(events[i]);
if (inviteList.length==0){ // if guests were found in checkInvites() then don't read it from event since checkInvites() added them to the cal but this event is not yet updated
var list = events[i].getGuestList();
for(n=0;n<list.length;++n){inviteList.push(list[n].getEmail())};
}else{
for(var n in inviteList){
events[i].addGuest(inviteList[n]);
}
}
row.push(inviteList.join(', '));
logArray.push(row);
}
}
// Logger.log(logArray);
if(logArray.length==0){continue};
try{
var sheetToWrite = ss.insertSheet(calName,ss.getNumSheets());// create sheet if doesn't exist
}catch(err){
var sheetToWrite = ss.getSheetByName(calName);// else open it
}
sheetToWrite.getRange(1,1,logArray.length,logArray[0].length).setValues(logArray).setHorizontalAlignment('left'); // enhance formating
sheetToWrite.getRange(1,1,1,logArray[0].length).setBackground('#EEA').setBorder(true,true,true,true,true,true).setHorizontalAlignment('left').setFontSize(12);
for(var w in logArray[0]){
sheetToWrite.setColumnWidth(Number(w)+1,180);
}
}
}
function checkInvites(event){
var email = []
var title = event.getTitle();
if(title.indexOf('#')==-1){return email};
email = title.match(/([\w-\.]+)#((?:[\w]+\.)+)([a-zA-Z]{2,4})/g);
Logger.log('email var = '+email);
return email;
}
function delsheets(){
var numbofsheet = ss.getNumSheets();// check how many sheets in the spreadsheet
for (var pa=numbofsheet-1;pa>0;pa--){
ss.setActiveSheet(ss.getSheets()[pa]);
if(ss.getSheets()[pa].getSheetName()!='calNames'){
ss.deleteActiveSheet(); // delete sheets begining with the last one
Utilities.sleep(400);
}
}
SpreadsheetApp.flush();
}
// This small function is to get the list of calendar names & Ids that you have access to, please edit the calNames sheet to keep only the ones you want to monitor (without empty rows).
function Callist(){
calNamesSheet.getDataRange().clearContent();
var list = new Array();
var store = new Array();
list = CalendarApp.getAllCalendars()
for (n=0;n<list.length;++n){
var name = list[n].getName() ;
var id = list[n].getId() ;
store.push( [name,id])
}
calNamesSheet.getRange(1,1,store.length,store[0].length).setValues(store);
}
// Serge insas - 08-2014