Mirra
BuildEvents

Google Calendar Events

Google Calendar events fire when calendar events are created, updated, or deleted in your connected Google Calendar. These events provide complete event details including times, attendees, location, and recurrence rules.


Event Types

calendar.event_created

The calendar.event_created event fires when a new event is created in your Google Calendar. This event captures all event details including attendees, location, and recurrence rules.

Event Type:

type: 'calendar.event_created'
source: 'google-calendar'

Fields:

content.text (string)

Event summary (title).

content.contentType (ContentType)

Always 'calendar_event' for calendar events.

actor.name (string)

Display name of the event creator.

context (null)

Always null for calendar events as they don't have channel context.

calendar.eventId (string)

Google Calendar event ID. Use this for updating or deleting the event.

calendar.summary (string)

Event title or summary.

calendar.description (string)

Event description or notes. Empty string if no description.

calendar.location (string | null)

Event location or meeting room. Null if no location specified.

calendar.startTime (Date)

Event start time as Date object.

calendar.endTime (Date)

Event end time as Date object.

calendar.isAllDay (boolean)

True if the event is an all-day event.

calendar.creator (EmailAddress)

Event creator with email and optional name.

FieldTypeDescription
creator.emailstringCreator's email address
creator.namestring | nullCreator's display name
calendar.attendees (EmailAddress[])

Array of attendee email addresses with optional names. Empty array if no attendees.

calendar.recurrence (RecurrenceRule | null)

Recurrence rule for repeating events. Null for one-time events.

FieldTypeDescription
frequency'daily' | 'weekly' | 'monthly' | 'yearly'How often the event repeats
intervalnumberRepeat every N units of frequency
untilDate | nullEnd date for recurrence
countnumber | nullNumber of occurrences

Example - Event Reminder:

export async function handler(event, context) {
  // Calculate reminder time (15 minutes before event)
  const eventTime = event.calendar.startTime;
  const reminderTime = new Date(eventTime.getTime() - 15 * 60 * 1000);
  
  // Schedule notification
  await mirra.notifications.schedule({
    time: reminderTime,
    message: `📅 Reminder: ${event.calendar.summary} in 15 minutes`,
    data: {
      eventId: event.calendar.eventId,
      location: event.calendar.location,
      attendees: event.calendar.attendees.length
    }
  });
  
  return { success: true };
}

Example - Meeting Logger:

export async function handler(event, context) {
  // Only track meetings with attendees
  if (event.calendar.attendees.length === 0) {
    return { success: true, skipped: true };
  }
  
  // Log to spreadsheet
  await mirra.google.sheets.appendRow({
    spreadsheetId: 'your-sheet-id',
    sheetName: 'Meetings',
    values: [
      event.calendar.summary,
      event.calendar.startTime.toISOString(),
      event.calendar.endTime.toISOString(),
      event.calendar.location || 'No location',
      event.calendar.attendees.length,
      event.calendar.attendees.map(a => a.email).join(', ')
    ]
  });
  
  return { success: true };
}

Example - Pre-Meeting Preparation:

export async function handler(event, context) {
  // Only for meetings starting within next hour
  const now = new Date();
  const hourFromNow = new Date(now.getTime() + 60 * 60 * 1000);
  
  if (event.calendar.startTime > hourFromNow) {
    return { success: true, skipped: true };
  }
  
  // Send Telegram reminder with details
  const attendeeList = event.calendar.attendees
    .map(a => `• ${a.name || a.email}`)
    .join('\n');
  
  await mirra.telegram.sendMessage({
    chatId: 'your-chat-id',
    text: `📅 Upcoming Meeting:\n\n${event.calendar.summary}\n\nWhen: ${event.calendar.startTime.toLocaleString()}\nWhere: ${event.calendar.location || 'No location'}\n\nAttendees:\n${attendeeList}`
  });
  
  return { success: true };
}

Subscription Examples:

// All calendar events
{
  "eventType": "calendar.event_created"
}
 
// Only meetings with attendees
{
  "eventType": "calendar.event_created",
  "conditions": [
    {
      "field": "calendar.attendees",
      "operator": "exists"
    }
  ]
}
 
// Events with specific keywords in title
{
  "eventType": "calendar.event_created",
  "conditions": [
    {
      "field": "calendar.summary",
      "operator": "contains",
      "value": "standup"
    }
  ]
}
 
// All-day events
{
  "eventType": "calendar.event_created",
  "conditions": [
    {
      "field": "calendar.isAllDay",
      "operator": "equals",
      "value": true
    }
  ]
}

calendar.event_updated

The calendar.event_updated event fires when an existing calendar event is modified. This includes changes to time, location, attendees, or any other event property.

Event Type:

type: 'calendar.event_updated'
source: 'google-calendar'

Fields:

Same as calendar.event_created. All fields reflect the updated event state.

Example - Change Notification:

export async function handler(event, context) {
  // Notify about event changes
  await mirra.telegram.sendMessage({
    chatId: 'your-chat-id',
    text: `📅 Event Updated: ${event.calendar.summary}\n\nNew time: ${event.calendar.startTime.toLocaleString()}\nLocation: ${event.calendar.location || 'None'}`
  });
  
  return { success: true };
}

calendar.event_deleted

The calendar.event_deleted event fires when a calendar event is deleted.

Event Type:

type: 'calendar.event_deleted'
source: 'google-calendar'

Fields:

calendar.eventId (string)

ID of the deleted event.

calendar.summary (string)

Title of the deleted event for reference.

Example - Deletion Logger:

export async function handler(event, context) {
  // Log deleted events
  await mirra.memory.create({
    type: 'calendar_deletion',
    content: `Event deleted: ${event.calendar.summary}`,
    metadata: {
      eventId: event.calendar.eventId,
      deletedAt: event.timestamp
    }
  });
  
  return { success: true };
}

Common Use Cases

Meeting Prep Assistant

export async function handler(event, context) {
  // Only for meetings with 3+ attendees
  if (event.calendar.attendees.length < 3) {
    return { success: true, skipped: true };
  }
  
  // Create meeting prep checklist 24 hours before
  const prepTime = new Date(event.calendar.startTime.getTime() - 24 * 60 * 60 * 1000);
  
  await mirra.assignments.create({
    title: `Prep for: ${event.calendar.summary}`,
    description: `Prepare for meeting with ${event.calendar.attendees.length} attendees`,
    dueDate: prepTime,
    metadata: {
      eventId: event.calendar.eventId,
      location: event.calendar.location,
      attendees: event.calendar.attendees.map(a => a.email)
    }
  });
  
  return { success: true };
}

Time Tracking

export async function handler(event, context) {
  // Calculate meeting duration
  const durationMs = event.calendar.endTime.getTime() - event.calendar.startTime.getTime();
  const durationHours = durationMs / (1000 * 60 * 60);
  
  // Log to time tracking sheet
  await mirra.google.sheets.appendRow({
    spreadsheetId: 'time-tracking-sheet-id',
    sheetName: 'Meetings',
    values: [
      event.calendar.startTime.toISOString().split('T')[0], // Date
      event.calendar.summary,
      durationHours.toFixed(2),
      event.calendar.attendees.length,
      event.calendar.location || 'Virtual'
    ]
  });
  
  return { success: true };
}

Recurring Meeting Tracker

export async function handler(event, context) {
  // Only track recurring meetings
  if (!event.calendar.recurrence) {
    return { success: true, skipped: true };
  }
  
  const recurrence = event.calendar.recurrence;
  
  // Store recurring meeting info
  await mirra.memory.create({
    type: 'recurring_meeting',
    content: `${event.calendar.summary} - ${recurrence.frequency}`,
    metadata: {
      eventId: event.calendar.eventId,
      frequency: recurrence.frequency,
      interval: recurrence.interval,
      until: recurrence.until,
      attendees: event.calendar.attendees.length
    }
  });
  
  return { success: true };
}

See Also

On this page