Spots emails asking for a meeting, finds times your calendar is free, and replies offering them.
Uses
Gmail
Google Calendar
OpenAI
Reply to meeting requests with open times
yourName to blank.Set yourName to blank.timeZone to blank.Set timeZone to blank.dailyMeetingTimes to 10:00, 14:00, 16:00.Set dailyMeetingTimes to 10:00, 14:00, 16:00.meetingLengthMinutes to 30.Set meetingLengthMinutes to 30.daysToLookAhead to 10.Set daysToLookAhead to 10.timesToOffer to 3.Set timesToOffer to 3.maxEmails to 15.Set maxEmails to 15.handledLabel to Meeting-times-checked.Set handledLabel to Meeting-times-checked.calendarId to primary.Set calendarId to primary.@handledLabel'. Save it as inbox.List emails matching '-label:@handledLabel'. Save it as inbox.meetingRequests to an empty list.Set meetingRequests to an empty list.email in inbox.emails:For each email in inbox.emails:messageId to blank.Set messageId to blank.subjectText to blank.Set subjectText to blank.messageText to blank.Set messageText to blank.readErrorIf a step below fails, save the error as readErrorTry
email.id and save it as messageId.Trim email.id and save it as messageId.email.subject and save it as subjectText.Trim email.subject and save it as subjectText.email.body and save it as messageText.Trim email.body and save it as messageText.On error
readError as text.Show in the output: Skipped an email that is missing its id, subject or body: readError as text.messageId is empty or messageText is emptyIf messageId is empty or messageText is emptyYes
No
No steps
verdict to blank.Set verdict to blank.classifyErrorIf a step below fails, save the error as classifyErrorTry
yourName that still needs a time agreed.Ask OpenAI: 'Decide whether this email is asking to arrange a meeting, call or appointment with yourName that still needs a time agreed.
Reply with exactly one word: yes or no. Reply no if a time has already been agreed, if the message only confirms, moves or cancels an existing meeting, or if it is a newsletter, receipt, notification or marketing email.
Subject: subjectText
messageText'. Save it as classification.classification.response_text lowercase and save it as verdict.Make classification.response_text lowercase and save it as verdict.On error
@subjectText is a meeting request, so it was left for the next run: classifyError as text.Show in the output: Could not tell whether @subjectText is a meeting request, so it was left for the next run: classifyError as text.verdict isn't emptyIf verdict isn't emptyYes
verdict starts with yesIf verdict starts with yesYes
meetingRequests and save it as meetingRequests.Add a record of id, subject, and text to the end of meetingRequests and save it as meetingRequests.No
handledLabel to email messageId.Add label handledLabel to email messageId.No
No steps
meetingRequests isn't emptyIf meetingRequests isn't emptyYes
openSlots to an empty list.Set openSlots to an empty list.dayOffset to 1.Set dayOffset to 1.dayOffset is less than or equal to daysToLookAhead and the length of…:While dayOffset is less than or equal to daysToLookAhead and the length of…:timeZone shifted by dayOffset days split by T and save it as day. Get the first item of today's date in timeZone shifted by dayOffset days split by T and save it as day.day is a weekend If not day is a weekendYes
slotTime in dailyMeetingTimes split by ,:For each slotTime in dailyMeetingTimes split by ,:openSlots is greater than or equal to timesToOffer If the length of openSlots is greater than or equal to timesToOfferYes
No
No steps
slotTime and save it as clockTime. Trim slotTime and save it as clockTime.clockTime is empty If clockTime is emptyYes
No
No steps
startsAt to dayT@clockTime. Set startsAt to dayT@clockTime.startsAt shifted by meetingLengthMinutes minutes split by . and save it as endsAt. Get the first item of startsAt shifted by meetingLengthMinutes minutes split by . and save it as endsAt.startsAt to endsAt. Save it as availability. Check if the calendar is free from startsAt to endsAt. Save it as availability.availability.isAvailable is yes If availability.isAvailable is yesYes
day, day at clockTime to the end of openSlots and save it as openSlots.Add the weekday name of day, day at clockTime to the end of openSlots and save it as openSlots.No
No steps
No
No steps
dayOffset. Add 1 to dayOffset.openSlots is emptyIf openSlots is emptyYes
daysToLookAhead days, so no times were offered. Add more times or raise 'daysToLookAhead', then run it again.Stop and report a problem: Your calendar is busy at every time in the 'dailyMeetingTimes' step for the next daysToLookAhead days, so no times were offered. Add more times or raise 'daysToLookAhead', then run it again.No
No steps
offeredTimes to - openSlots joined by "Set offeredTimes to - openSlots joined by
- .request in meetingRequests:For each request in meetingRequests:replyBody to blank. Set replyBody to blank.draftError If a step below fails, save the error as draftErrorTry
yourName.Ask OpenAI: 'Write the plain-text body of a short, friendly reply to the email below, on behalf of yourName.
Offer these times and ask the sender to pick one, or to suggest another time if none of them work. Use only these times - do not invent, move or add any others, and do not convert them to another time zone.
Times to offer (all times timeZone):
offeredTimes
Each meeting is meetingLengthMinutes minutes long.
Write the reply body only - no subject line, no quoted text and no placeholders to fill in. Sign off as yourName.
Subject: request.subject
request.text'. Save it as draft.draft.response_text and save it as replyBody.Trim draft.response_text and save it as replyBody.On error
@request.subject, so it was left for the next run: draftError as text.Show in the output: Could not draft a reply to @request.subject, so it was left for the next run: draftError as text.replyBody isn't empty If replyBody isn't emptyYes
request.Reply to email request.replyBodyhandledLabel to email request.Add label handledLabel to email request.No
No steps
No
No steps