Jump to content
Claris Engage 2025 - March 25-26 Austin Texas ×
The Claris Museum: The Vault of FileMaker Antiquities at Claris Engage 2025! ×

This topic is 4622 days old. Please don't post here. Open a new topic instead.

Recommended Posts

Posted (edited)

Been doing this as the machines I want it to work on are PC so Applescript won't do.

Can put a timed item or all-day into your calendar, just feed it your account details and Cal name, needs java 1.6, and a bunch of Google jar files

gdata-base

gdata-calendar

gdata-calendar-meta

gdata-client

gdata-core

guava

Sure there are more elegant ways to achieve this if anyone wants to amend it... or add any error trapping


// gCalMake( fm_title ; fm_content ; fm_date ; fm_startTime ; fm_endTime ; fm_place ; fm_remind )

// 2010/10/10 JR

// v1

// takes fm_title, fm_content, fm_date, fm_startTime

// optional fm_place

// if fm_endTime is null makes it a one hour appointment

// if fm_remind = 0 sets no reminder else sets reminder in minutes



import com.google.gdata.client.calendar.*

import com.google.gdata.data.*

import com.google.gdata.data.calendar.*

import com.google.gdata.data.extensions.*

import com.google.gdata.util.*

import java.net.URL

import java.text.SimpleDateFormat



myService = new CalendarService( "CAL_NAME" )

try {

	myService.setUserCredentials( "[email protected]", "PASSWORD" )

	} catch ( AuthenticationException e ) {

		// Invalid credentials

		e.printStackTrace()

	}

postUrl = new URL( "https://www.google.com/calendar/feeds/[email protected]/private/full" )

myEntry = new CalendarEventEntry()

myEntry.setTitle( new PlainTextConstruct( fm_title ) )

myEntry.setContent( new PlainTextConstruct( fm_content ) )

myEntry.addLocation( new Where( "", "", fm_place ) )

eventTimes = new When()

if ( fm_date.length() < 10 ) {

	// needs 2010/mo/dd

	return "Error"

}

if ( fm_startTime == "all" ) {

	st = ( fm_date + "T01:00:00" ).replaceAll( "/", "-")

} else {

	st = ( fm_date + "T" + fm_startTime + ":00" ).replaceAll( "/", "-")

}

if (fm_endTime == null) {

	et = ( fm_date + "T" + ( fm_startTime ) + ":00")

	et= et.replaceAll( "/", "-")

} else {

	et = (fm_date + "T" + fm_endTime + ":00")

	et = et.replaceAll( "/", "-")

}

startTime = DateTime.parseDateTime( st )

if ( fm_endTime == null ) {

	//add an hour

	endd = DateTime.parseDateTime( st ).getValue() + 3600000L

	endTime = new DateTime( endd )

} else {

	endTime = DateTime.parseDateTime ( et )

}

if ( fm_startTime == "all" ) {

	startTime.setDateOnly( true )

	endTime.setDateOnly( true )

}

eventTimes.setStartTime( startTime )

eventTimes.setEndTime( endTime )

myEntry.addTime( eventTimes )

CalendarEventEntry insertedEntry = myService.insert( postUrl, myEntry )

// do the reminder after event is created

if ( fm_startTime != "all" ) {

	if ( fm_remind != "0" ) {

		reminder = new Reminder()

		reminder.minutes = fm_remind.toInteger()

		// change to ALL, ALERT, SMS, MAIL as reqd

		reminder.setMethod( com.google.gdata.data.extensions.Reminder$Method.ALERT )

		insertedEntry.getReminder().add( reminder )

		insertedEntry.update()

	}

}

return true

Edited by Guest
Posted (edited)

And here is some code to get the diary entries between two dates, end date == null means same day

As above needs your user and password and could do with some error trapping


// gCalFind( fm_dateStart ; fm_dateEnd )

// 2010/10/10 JR

// v1

// Search gCal between dates, returns date and time ordered list

// Returns "No entry", and replaces gCal meeting notice hyperlink

// Dates yyyy/mm/dd



import com.google.gdata.client.calendar.*

import com.google.gdata.data.*

import com.google.gdata.data.calendar.*

import com.google.gdata.data.extensions.*

import com.google.gdata.util.*

import com.google.gdata.data.calendar.*

import java.net.URL

import java.text.SimpleDateFormat



myService = new CalendarService("CALNAME")

bigresult = alist = dlist = ""

dateFormat = new SimpleDateFormat("HH:mm")

// change this for date display

// http://download.oracle.com/javase/1.4.2/docs/api/java/text/SimpleDateFormat.html

dayTitle = new SimpleDateFormat("EE dd MMM")

try {

	myService.setUserCredentials("[email protected]", "PASSWORD")

	} catch (AuthenticationException e) {

		// Invalid credentials

		e.printStackTrace()

		return "Error"

}

//

feedUrl = new URL("https://www.google.com/calendar/feeds/default/private/full")

if ( fm_dateStart.length() < 10 ) {

	return "Error"

}

//

sd = ( fm_dateStart + "T00:00:00" ).replaceAll( "/", "-")

dstart = DateTime.parseDateTime( sd ).getValue()

//

if ( fm_dateEnd == null ) {

	ed = ( fm_dateStart + "T23:59:00" ).replaceAll( "/", "-")

	dend = dstart

	int k = 1

} else {

	ed = ( fm_dateEnd + "T23:59:00" ).replaceAll( "/", "-")

	dend = DateTime.parseDateTime( ed ).getValue()

	k = Math. ceil( ( dend - dstart) / 86400000 ).toInteger()

	ed = ( fm_dateStart + "T23:59:00" ).replaceAll( "/", "-")

}

// k = no of days

for ( int j = 0; j < k; ++j ) {

	// BIG LOOP HERE

	myQuery = new CalendarQuery(feedUrl)

	myQuery.setMinimumStartTime( DateTime.parseDateTime( sd ) )

	myQuery.setMaximumStartTime( DateTime.parseDateTime( ed ) )

	resultFeed = myService.query( myQuery, CalendarEventFeed.class )

	if ( resultFeed.getEntries().size() == 0 ) {

		dlist = dayTitle.format( dstart ) + "n"

		result = "No entries today" + "n"

		bigresult = bigresult + dlist + result + "n"

		dl = dlist

		dlist = result = ""

		dstart = dstart + 86400000

		dend = dstart + 86390000

		sd = new DateTime( dstart ).toString()

		ed = new DateTime( dend ).toString()

	} else {

	int i = 0

	dl = dr = dt = result = ""

	req = resultFeed.getEntries()

	req.each { it -> resultFeed.getEntries().get(i)

	myTitle = it.getTitle().getPlainText()

	myContent = it.getPlainTextContent()

	myDate = it.getTimes()

	Boolean hyp = myContent.contains("HYPERLINK")

	if ( hyp ) {

		myContent = "weblink"

	}

	dts = dateFormat.format( it.getTimes().get(0).getStartTime().getValue() )

	dte = dateFormat.format( it.getTimes().get(0).getEndTime().getValue() )

	dt = dayTitle.format( it.getTimes().get(0).getStartTime().getValue() )

	// if this.date == last.date do nothing else make it the same and make result = date.newline

	if ( dt == dl ) {

		} else {

		dl = dt

		dr = dt + "n"

	}

	if ( dts == dte) {

	theDate = "0 All Day" + "t"

	myTitle = myTitle.toUpperCase()

	} else {

	theDate = dts + " " + dte

	}

	if ( myContent != "" ) { content = "  " + myContent.replaceAll( "n", " | ") } else { content = "" }

	alist = alist + theDate + "tt" + myTitle + content + "n"

	dlist = dlist + dr

	dr = ""

	dts = dte = ""

	}

	if (alist != null) {

		fma = alist.tokenize("n")

		fma.sort().each {

			result = result + it + "n"

		}

	} else {

	}

	dstart = dstart + 86400000

	dend = dstart + 86390000

	sd = new DateTime( dstart ).toString()

	ed = new DateTime( dend ).toString()

	bigresult = bigresult + dlist + result + "n"

	alist = dlist = result = ""

	}

	//j++

}

//

return bigresult.replaceAll( "0 All", "All")

Edited by Guest
Posted

Hi John

this is nice. And I think this can become a part of one of my solutions (actually I am sure, I have customers asking me all the time to play with iCal, and update their iPhones, and google calendars, so this is really a nice approach).

In this case I would need to know the ID of the event on the google calendar. So just as a small addition, I think it might be better to return the UID of the event instead of simply "true". You can achieve this by returning insertedEntry.getIcalUID();

If you don't mind I am going to play around with your code, so you can actually edit and modify those events from within FileMaker. I will post my results here!

Thanks for this nice idea!

Andries

Posted

Hi John

I adapted your script a little and added an extra parameter 'link' to it. If the parameter is empty it will create a new entry in the event. The function returns the url of the event it created. This url should be provided as parameter for this URL if you want to update the event in a later call.

I also abstracted out the username, password and calendar service so you can pass them as parameters.


// gCalMake( fm_title ; fm_content ; fm_date ; fm_startTime ; fm_endTime ; fm_place ; fm_remind ; link ; userName ; password ; calendarService )

// 2010/10/10 JR

// v1

// takes fm_title, fm_content, fm_date, fm_startTime

// optional fm_place

// if fm_endTime is null makes it a one hour appointment

// if fm_remind = 0 sets no reminder else sets reminder in minutes



import com.google.gdata.client.calendar.*

import com.google.gdata.data.*

import com.google.gdata.data.calendar.*

import com.google.gdata.data.extensions.*

import com.google.gdata.util.*

import java.net.URL

import java.text.SimpleDateFormat



boolean editEvent;

String link = link;





myService = new CalendarService( calendarService )

try {

    myService.setUserCredentials( userName, password )

    } catch ( AuthenticationException e ) {

        // Invalid credentials

        e.printStackTrace()

    }



postUrl = new URL( "https://www.google.com/calendar/feeds/" + userName+ "/private/full" )



if ( link == null ) {

	myEntry = new CalendarEventEntry()

	editEvent = false;



} else {

	editUrl = new URL ( link )

	myEntry = myService.getEntry(editUrl, EventEntry.class);

	editEvent = true;

}



myEntry.setTitle( new PlainTextConstruct( fm_title ) )

myEntry.setContent( new PlainTextConstruct( fm_content ) )

myEntry.addLocation( new Where( "", "", fm_place ) )

eventTimes = new When()

if ( fm_date.length() < 10 ) {

    // needs 2010/mo/dd

    return "Error"

}

if ( fm_startTime == "all" ) {

    st = ( fm_date + "T01:00:00" ).replaceAll( "/", "-")

} else {

    st = ( fm_date + "T" + fm_startTime + ":00" ).replaceAll( "/", "-")

}



if (fm_endTime == null) {

    et = ( fm_date + "T" + ( fm_startTime ) + ":00")

    et= et.replaceAll( "/", "-")

} else {

    et = (fm_date + "T" + fm_endTime + ":00")

    et = et.replaceAll( "/", "-")

}



startTime = DateTime.parseDateTime( st )



if ( fm_endTime == null ) {

    //add an hour

    endd = DateTime.parseDateTime( st ).getValue() + 3600000L

    endTime = new DateTime( endd )

} else {

    endTime = DateTime.parseDateTime ( et )

}



if ( fm_startTime == "all" ) {

    startTime.setDateOnly( true )

    endTime.setDateOnly( true )

}

eventTimes.setStartTime( startTime )

eventTimes.setEndTime( endTime )

myEntry.addTime( eventTimes )



//EventEntry insertedEntry;

if ( editEvent ){

	EventEntry insertedEntry = myService.update(editUrl, myEntry);	

return insertedEntry.getSelfLink().getHref();

} else {

	CalendarEventEntry insertedEntry = myService.insert( postUrl, myEntry );	

	return insertedEntry.getSelfLink().getHref();

}

//return insertedEntry.getSelfLink().getHref();	

However I have a question about the end of the script, namely I need to use two returns, although they seem exactly the same. Except that in one case insertedEntry is a CalendarEventEntry and in the other case it is a EventEntry. However both objects should respond to the method I provide.

If I place the return only once at the end (outside the if statement, the line is now commented ) I get as an error "No such property: insertedEntry for class: Script1." Can someone clarify why this error is thrown?

Posted

Andries

Thanks

Very cool...

If you did a returnderUID.replaceAll ( PostURL, "") on the returned link it would be a shorter thing to store and slightly more obscure..

then if link != null link = PostURL+link

Am going to do some more and add hours and days to the reminders.

I already have about 4 uses for this...

The Google API seems to be a bit hit and miss, this is a really great find. Presumably you could use this to return the values of a saved entry too...?

Posted (edited)

Andries

The UPDATE is an EventEntry class and the INSERT is an CalendarEventEntry class, seems like a Google thing!!

However the content of both are java.lang.String which is a complete link to the calendar item

So if we make the end of both parts of the {if else}

result = insertedEntry.....

we can have one return result at the end, which I will do a replace on.


rep = postUrl.toString().replaceAll("@", "%40") + ""

return result.replaceAll( rep, "")





If I add the reminder code on at the end it will only work on and add not an update... and if I update an event WITH

a reminder it removes the reminder..



changed the code in the middle to correctly return an all day event which Outlook can read, and cope with odd values in endTime field





sdf = new SimpleDateFormat("yyyy-MM-dd")

if (fm_endTime == null) {

	// no end time add an hour

	if ( fm_startTime == "all") {

		st = ( fm_date + "T01:00:00" ).replaceAll( "/", "-")

	} else {

		st = ( fm_date + "T" + fm_startTime + ":00" ).replaceAll( "/", "-")

	}

	endd = DateTime.parseDateTime( st ).getValue() + 3600000L

	endTime = new DateTime( endd )

} else {

	// use end time

	et = (fm_date + "T" + fm_endTime + ":00")

	et = et.replaceAll( "/", "-")

	endTime = DateTime.parseDateTime ( et )

}



if ( fm_startTime == "all" ) {

	st = ( fm_date + "T01:00:00" ).replaceAll( "/", "-")

	olddate = sdf.parse(fm_date.replaceAll( "/", "-"))

	cal = Calendar.getInstance() 

	cal.setTime(olddate) 

	cal.add(Calendar.DATE, 1)

	fm_date2 = sdf.format(cal.getTime())

	et = ( fm_date2 + "T01:00:00")

	endTime = DateTime.parseDateTime ( et )

} else {

	st = ( fm_date + "T" + fm_startTime + ":00" ).replaceAll( "/", "-")

}



startTime = DateTime.parseDateTime( st )

if ( fm_startTime == "all" ) {

	startTime.setDateOnly( true )

	endTime.setDateOnly( true )

}

Edited by Guest
Posted (edited)

Changed the end to add reminder to be days hours or minutes(default) if fm_remind has unit at end

e.g. 15m, 2h, 1d

will only do days if it is an all-day event


eventTimes.setStartTime( startTime )

eventTimes.setEndTime( endTime )

myEntry.addTime( eventTimes )



// fm_remind e.g. 1d for day, 3h for hour, 15m or 15 for minutes

if ( fm_remind.endsWith('d') || fm_remind.endsWith('h') || fm_remind.endsWith('m') ) {

	remUnit = fm_remind.charAt(fm_remind.length() - 1 )

	fm_remind = fm_remind.substring(0, fm_remind.length() - 1 ).toInteger()

} else {

	remUnit = "m"

	fm_remind = fm_remind.toInteger()

}



if ( editEvent ){

	EventEntry editEntry = myService.update(editUrl, myEntry)

	result = editEntry.getSelfLink().getHref()

	myQuery = new CalendarQuery(postUrl)

	CalendarEventFeed evFeed = myService.query( myQuery, CalendarEventFeed.class )

	CalendarEventEntry calEntry = evFeed.getEntries().get(0)

	reminder = new Reminder()

	reminder.setMethod(Reminder.Method.ALERT)

	// set reminder if start time not 'all' and reminder has value OR it is all and remind is a days value

if ( fm_startTime != "all" && fm_remind != 0 || fm_startTime == "all" && remUnit == "d" ) {

		if ( remUnit == "d") {

			reminder.setDays(fm_remind)

		} else if ( remUnit == "h" ) {

			reminder.setHours(fm_remind)

		} else {

			reminder.setMinutes(fm_remind)

		}

		calEntry.getReminder().add( reminder )

		calEntry.update()

	}

} else {

	CalendarEventEntry calEntry = myService.insert( postUrl, myEntry )    

	result = calEntry.getSelfLink().getHref()

	reminder = new Reminder()

	reminder.setMethod( Reminder$Method.ALERT )

	// set reminder if start time not 'all' and reminder has value OR it is all and remind is a days value

	if ( fm_startTime != "all" && fm_remind != 0 || fm_startTime == "all" && remUnit == "d" ) {

		if ( remUnit == "d") {

			reminder.setDays(fm_remind)

		} else if ( remUnit == "h" ) {

			reminder.setHours(fm_remind)

		} else {

			reminder.setMinutes(fm_remind)

		}

		calEntry.getReminder().add( reminder )

		calEntry.update()

	}

}



return result

Edited by Guest
Changed the code to update reminder rather than wipe it out
  • 1 year later...
Posted

Hello,

I try to run google API on scriptmaster.

I add the jar libraries (gdata-base, gdata-calendar, gdata-calendar-meta, gdata-client, gdata-core, guava, jsr305)

but I get an error from the start

java.lang.NoClassDefFoundError: com/google/api/client/auth/oauth2/Crendtial

what's the problem in my script ?

thanks

Posted

Google are moving to OAuth2 as their preferred method of authenticating your application with users, as it doesn't involve sending a user password inside the URL string.

The api calls above are being deprecated in some cases in light of this and there is a whole new set of methods to learn and follow.

I am talking about this at the UK Technet in a few weeks so will try and post something after that for you.

For now read up

http://code.google.com/p/google-api-java-client/wiki/OAuth2

This topic is 4622 days old. Please don't post here. Open a new topic instead.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...

Important Information

By using this site, you agree to our Terms of Use.