Monday, October 22, 2018

#1 2018-06-04 12:47:42 am

akim
Member
Registered: 2010-04-04
Posts: 80

w EventKit Predicate to find Event UID

If I have an event UID, how do I script EventKit to  isolate that one event, using a predicate that refers to the UID string. I wrote the following script to show that I can isolate EventKit events by dates, but have to resort to a loop to isolate EventKit events by a sharedUID.

I used Shane's "CalendarLib EC" to gather the elements of the event itself in that loop.

The following applescript example finds an event whose UID is "34C4450E-70C0-48D5-B94C-03240284C1BD" scheduled in a calendar named "Personal Web" in period ranging from 7 days prior to 5 days hence.

The script correctly yields the following:
{event_external_ID:"34C4450E-70C0-48D5-B94C-03240284C1BD", event_location:missing value, event_end_date:date "Sunday, June 3, 2018 at 2:00:00 PM", event_start_date:date "Sunday, June 3, 2018 at 1:45:00 PM", event_time_zone:"America/Los_Angeles", event_status:"confirmed", event_description:missing value, event_url:missing value, event_organizer:missing value, calendar_type:"cloud", all_day:false, event_creation_date:date "Sunday, June 3, 2018 at 5:32:03 PM", event_original_date:missing value, event_attendees:{}, event_is_recurring:false, event_summary:"Trial Event", calendar_name:"Personal Web"}

How can I script the final repeat loop using a predicate method?

Applescript:

use AppleScript version "2.4"
use scripting additions
use framework "Foundation"
use framework "EventKit"
use script "CalendarLib EC"

set targetUID to "34C4450E-70C0-48D5-B94C-03240284C1BD"
set listOfCalNames to {"Personal Web"} -- list of one or more calendar names
set DaysBefore to 7
set DaysAhead to 5
set eventInformation to my getEventInfoForUID:targetUID inCalendarList:listOfCalNames fromDaysBefore:DaysBefore toDaysAhead:DaysAhead
on getEventInfoForUID:targetUID inCalendarList:listOfCalNames fromDaysBefore:DaysBefore toDaysAhead:DaysAhead
   
   # Create event store and get access to Calendars
   set theEKEventStore to current application's EKEventStore's alloc()'s init()
   theEKEventStore's requestAccessToEntityType:0 completion:(missing value)
   
   # Get event store authorization status
   my authorizationStatus()
   
   # Arrange date predicates
   set {DaysBehindDate, DaysAheadDate} to my prepareDateRangeFromDaysBefore:DaysBefore toDaysAhead:DaysAhead
   
   # Arrange calendar predicate
   set calsToSearch to my getCalendarsToSearch:listOfCalNames withEKEventStore:theEKEventStore
   if calsToSearch is false then return false --abort script
   
   # Find matching events for date using predicate method
   set theDatePred to theEKEventStore's predicateForEventsWithStartDate:DaysBehindDate endDate:DaysAheadDate calendars:calsToSearch
   set theEvents to (theEKEventStore's eventsMatchingPredicate:theDatePred)
   
   # Find matching event for UID using loop method
   # I am unable to write an EventKit predicate method
   set eventInformation to my LoopThroughEvents:theEvents ToGetEventInformationFromTargetUID:targetUID
end getEventInfoForUID:inCalendarList:fromDaysBefore:toDaysAhead:

on getCalendarsToSearch:listOfCalNames withEKEventStore:theEKEventStore
   --set calendar type for EventStore Predicate
   set listOfCaTypes to {0, 1, 2} -- list of one or more calendar types: : Local = 0, CalDAV/iCloud = 1, Exchange = 2, Subscription = 3, Birthday = 4
   
   -- get calendars that store events
   set theCalendars to theEKEventStore's calendarsForEntityType:0
   
   -- filter for desired calendars
   set theNSPredicate to current application's NSPredicate's predicateWithFormat_("title IN %@ AND type IN %@", listOfCalNames, listOfCaTypes)
   set calsToSearch to theCalendars's filteredArrayUsingPredicate:theNSPredicate
   if (count of calsToSearch) < 1 then set calsToSearch to false
   calsToSearch
end getCalendarsToSearch:withEKEventStore:

on authorizationStatus()
   -- check if app has access and authorization
   set authorizationStatus to current application's EKEventStore's authorizationStatusForEntityType:0 -- work around enum bug
   if authorizationStatus is not 3 then
       display dialog "Access must be given in System Preferences" & linefeed & "-> Security & Privacy first." buttons {"OK"} default button 1
       tell application "System Preferences"
           activate
           tell pane id "com.apple.preference.security" to reveal anchor "Privacy"
       end tell
       error number -128
   end if
end authorizationStatus

on prepareDateRangeFromDaysBefore:DaysBefore toDaysAhead:DaysAhead
   # create start date and end date for occurances
   --set nowNSDate variable to represent current UTC Universal Time-Coordinated date, previously Zulu Time Zone
   set nowDate to current application's NSDate's |date|
   
   --startOfDayForDate returns the first UTC moment of a given date as a date instance, based upon the current time zone.
   set todaysStartofDayDate to current application's NSCalendar's currentCalendar()'s startOfDayForDate:nowDate
   
   --set the days that will define the date predicate range
   set DaysBehindDate to todaysStartofDayDate's dateByAddingTimeInterval:(-1) * DaysBefore * days
   set DaysAheadDate to todaysStartofDayDate's dateByAddingTimeInterval:DaysAhead * days
   {DaysBehindDate, DaysAheadDate}
end prepareDateRangeFromDaysBefore:toDaysAhead:

on LoopThroughEvents:theEvents ToGetEventInformationFromTargetUID:targetUID
   # Question: What EventKit predicate method can avoid the following loop, so that a large list can be evaluated?
   repeat with anEvent in theEvents
       set shareUID to (anEvent's sharedUID as string)
       if targetUID is shareUID then
           return (event info for event anEvent)
           exit repeat
       end if
   end repeat
end LoopThroughEvents:ToGetEventInformationFromTargetUID:

Last edited by akim (2018-06-04 12:56:16 am)

Offline

 

#2 2018-06-04 06:10:22 am

Shane Stanley
Member
From:: Australia
Registered: 2002-12-07
Posts: 5454

Re: w EventKit Predicate to find Event UID

If I understand you correctly, this:

Applescript:

set theNSPredicate to current application's NSPredicate's predicateWithFormat:"calendarItemExternalIdentifier == %@" argumentArray:{targetUID}


Shane Stanley <sstanley@myriad-com.com.au>
www.macosxautomation.com/applescript/apps/
latenightsw.com

Offline

 

#3 2018-06-04 08:49:36 am

akim
Member
Registered: 2010-04-04
Posts: 80

Re: w EventKit Predicate to find Event UID

As shown below, I am far from mastering the Objective C EventKit language via Applescript.
Using the following instantiation of an NSPredicate,

Applescript:

   set theNSPredicate to current application's NSPredicate's predicateWithFormat:"calendarItemExternalIdentifier == %@" argumentArray:{targetUID}

I have tried three methods, yielding three different Applescript responses:

Applescript:

   set theEvents to (theEKEventStore's eventWithIdentifier:theNSPredicate)

-->-[NSComparisonPredicate length]: unrecognized selector sent to instance 0x604002042760

Applescript:

   set theEvents to (theEKEventStore's eventsMatchingPredicate:theNSPredicate)

-->predicate was not created with EKEventStore methods

Applescript:

   set theEvents to (theEKEventStore's eventWithIdentifier:targetUID)

-->'msng'

What might be an effective EventKit predicate command to isolate an event by means of its External Identifier?

Offline

 

#4 2018-06-04 05:27:18 pm

Shane Stanley
Member
From:: Australia
Registered: 2002-12-07
Posts: 5454

Re: w EventKit Predicate to find Event UID

That's a standard predicate, not specific to EventKit. It assumes you have a standard array, as you have in your code after using the dates-based predicate. So something like:

Applescript:

set theNSPredicate to current application's NSPredicate's predicateWithFormat:"calendarItemExternalIdentifier == %@" argumentArray:{targetUID}
set filteredEvents to theEvents's filteredArrayUsingPredicate:theNSPredicate


Shane Stanley <sstanley@myriad-com.com.au>
www.macosxautomation.com/applescript/apps/
latenightsw.com

Offline

 

Board footer

Powered by FluxBB

RSS (new topics) RSS (active topics)