john renfrew Posted October 10, 2010 Posted October 10, 2010 (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 October 10, 2010 by Guest
john renfrew Posted October 10, 2010 Author Posted October 10, 2010 (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 October 10, 2010 by Guest
andries Posted October 11, 2010 Posted October 11, 2010 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
andries Posted October 11, 2010 Posted October 11, 2010 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?
john renfrew Posted October 12, 2010 Author Posted October 12, 2010 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...?
john renfrew Posted October 12, 2010 Author Posted October 12, 2010 (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 October 12, 2010 by Guest
john renfrew Posted October 12, 2010 Author Posted October 12, 2010 (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 October 14, 2010 by Guest Changed the code to update reminder rather than wipe it out
webax Posted June 5, 2012 Posted June 5, 2012 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
john renfrew Posted June 6, 2012 Author Posted June 6, 2012 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
Recommended Posts
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 accountSign in
Already have an account? Sign in here.
Sign In Now