The script below is using applescript and is very close to a working version I need. The script was wrote by @CJK but he seems to have gone missing and I can't extend the script to fix it to do what I want as my applescript knowledge is terrible.
Here is the script:
#!/usr/bin/osascript
--------------------------------------------------------------------------------
###[ASObjC] Get Calendar Events (nikivi).applescript
#
# Retrieves from a user's Apple Calendar an enumerated list of events
# that fall within a specified date range. It does this independently of
# the macOS calendar application, using AppleScriptObjC. By default,
# events for the next 30 days are searched, and the title and date of the
# next upcoming event is returned. If no events occur within this time
# span, an empty list is returned.
#
# Input:
# %input% Either a single date or pair of dates
# that represent a range of dates between
# which events are searched
#
# Result:
# -1 Authorisation required
# ❮string❯ The details of the next event, if any,
# to fall on or between the given dates
# ❮empty list❯ No upcoming events
--------------------------------------------------------------------------------
# Author: CK
# Date Created: 2018-09-01
# Date Last Edited: 2018-10-09
--------------------------------------------------------------------------------
use framework "Foundation"
use framework "EventKit"
use scripting additions
--------------------------------------------------------------------------------
property this : a reference to current application
property EKAuthorised : a reference to 3
property EKEntityMaskEvent : a reference to EKEntityMaskEvent of this
property EKEntityTypeEvent : a reference to EKEntityTypeEvent of this
property EKEventStore : a reference to EKEventStore of this
property NSArray : a reference to NSArray of this
property NSDate : a reference to NSDate of this
property NSDateFormatter : a reference to NSDateFormatter of this
property NSDateInterval : a reference to NSDateInterval of this
property NSLocale : a reference to NSLocale of this
property NSMutableArray : a reference to NSMutableArray of this
property NSPredicate : a reference to NSPredicate of this
property NSSortDescriptor : a reference to NSSortDescriptor of this
property NSString : a reference to NSString of this
property NSTimeZone : a reference to NSTimeZone of this
--------------------------------------------------------------------------------
property EventStore : a reference to EKEventStore's alloc's init
property EventSources : a reference to EventStore's sources
global calendars
--------------------------------------------------------------------------------
property text item delimiters : space
--------------------------------------------------------------------------------
property |24hours| : 86399
property name : null
property date : current date
--------------------------------------------------------------------------------
###IMPLEMENTATION
#
#
# e.g. input: {"2018-01-01", current date}
on run input
if not Authorised() then return -1
if input's class = script then set the input to [current date, (current date) + 30 * days] -- A one-month time span
set [D1, D2] to the input
if D2's class = record then set [D1, D2] to D1 -- Automator
set calendars to EventStore's calendarsForEntityType:EKEntityTypeEvent
log the result's title as list
if timeUntilNextEvent() ≤ 0 then tell (enumeratedEventsByDate from D1 to D2 with birthdays)
log "Events list refreshed"
if the nextEvent() = null then return "No upcoming events"
tell the currentEvent() to set [my date, my name] to its [startDate, title]
log the currentEvent()
end tell
return the contents of {[my name, ":"], timeUntilNextEvent(), "min"} as text
end run
--------------------------------------------------------------------------------
###HANDLERS
#
#
on Authorised()
EventStore's requestAccessToEntityType:EKEntityMaskEvent completion:(missing value)
EKEventStore's authorizationStatusForEntityType:EKEntityMaskEvent
if the result ≠EKAuthorised then return false
true
end Authorised
on timeUntilNextEvent()
(my date) - (current date)
result / minutes as integer
end timeUntilNextEvent
# dateRange:
# Returns a list whose first and second items are AppleScript date objects
# that evaluate to midnight and 23:59:59, respectively, on the specified
# date. The input can be an AppleScript date object or a string value
# formatted as "yyyy-MM-dd".
on dateRange over D
local D
if D's class = date then
script
property date : D - (D's time)
on startDate()
my date
end startDate
on endDate()
(my date) + |24hours|
end endDate
end script
else
set DateFormatter to NSDateFormatter's alloc()'s init()
tell the DateFormatter
setLocale_(NSLocale's localeWithLocaleIdentifier:"en_US_POSIX")
setTimeZone_(NSTimeZone's timeZoneForSecondsFromGMT:(time to GMT))
setDateFormat_("yyyy-MM-dd")
NSDateInterval's alloc()'s initWithStartDate:dateFromString_(D) duration:|24hours|
end tell
end if
tell result to return [startDate() as date, endDate() as date]
end dateRange
# enumeratedEventsByDate:
# Searches for events that fall between the dates supplied, with the
# option to include or exclude birthday events. Both date parameters
# are optional, and will default to the current date if absent. The
# handler returns a script object that mimics an enumerated list, which
# contains the results of the search in date order. The order is
# reversed if the date parameters are reversed.
#
# Iterate through the event list using the nextEvent() or
# nextEventMatching handlers, the latter of which returns the next
# event that contains any matching parameter supplied. currentEvent()
# allows retrieval of the event at the current position in the list
# without advancing to the next event. allEvents() returns the list
# of events in one go.
#
# Each event is a record object containing the following properties:
# title, startDate, endDate, location, notes.
on enumeratedEventsByDate from D1 : null to D2 : null without birthdays
local D1, D2, birthdays
local ascending
global calendars
if D1 = null then set D1 to the current date
if D2 = null then set D2 to the current date
set [|D1*|, |D2*|] to [dateRange over D1, dateRange over D2]
set ascending to |D1*|'s item 1 < |D2*|'s item 1
if not ascending then set [|D1*|, |D2*|, D1, D2] to [|D2*|, |D1*|, D2, D1]
set D2 to item 2 of |D2*|
EventStore's predicateForEventsWithStartDate:D1 endDate:D2 calendars:calendars
EventStore's eventsMatchingPredicate:result
set EventsInDateRange to NSMutableArray's arrayWithArray:result
NSPredicate's predicateWithFormat:("! calendar.title CONTAINS[c] %@") argumentArray:["birthdays"]
if not birthdays then EventsInDateRange's filterUsingPredicate:result
NSSortDescriptor's sortDescriptorWithKey:(missing value) ascending:ascending selector:"compareStartDateWithEvent:"
EventsInDateRange's sortUsingDescriptors:[result]
script
property list : EventsInDateRange
property event : null
property all : EventsInDateRange's allObjects() as list
on nextEvent()
if (my list's |count|()) = 0 then return null
set E to my list's item 1
(my list)'s removeObjectAtIndex:0
E's dictionaryWithValuesForKeys:["title", "startDate", "endDate", "location", "notes"]
set my event to the result as record
end nextEvent
on currentEvent()
my event
end currentEvent
on nextEventMatching given name:title : null, date:D : missing value, location:addr : null
set E to false
repeat until result = true or E = null
set E to the nextEvent()
if E = null then exit repeat
copy [E's startDate, 0] to [D0, D0's time]
copy [E's endDate, |24hours|] to [D1, D1's time]
true is in [D ≥ D0 and D ≤ D1, E's title contains title, E's location contains addr]
end repeat
E
end nextEventMatching
on allEvents()
if all = {} then return {}
if the class of some item in all ≠record then
repeat with E in all
tell E to set its contents to dictionaryWithValuesForKeys_(["title", "startDate", "endDate", "location", "notes"]) as record
end repeat
end if
all
end allEvents
end script
end enumeratedEventsByDate
---------------------------------------------------------------------------❮END❯
Currently it returns events running as well as time until they end.
However I wish to change it so it returns the current event running and time until next event.
How it works now
Current event:
What it returns:
"đź“–: -94 min"
The 94 min is time until the event ends.
What it should show
Given this time and events:
It would return
đź“– 154
Where 154 is number of minutes before next event (learn applescript) in above case.
If there is no event running currently, it would show time until next event and the event title.
So given this:
It would return 153 learn applescript
. Where 153 minutes is the time until that event.
I also want to only consider one event group in Google Calendar (called 'Events'). As well as ignore all All Day
events.
Thank you a lot for anyone can help me make this script into reality. I would gladly pay for the time you spent writing it as I have been needing this for a long time in my workflow.