Skip to content

Instantly share code, notes, and snippets.

@wilmoore
Last active September 24, 2024 22:39
Show Gist options
  • Select an option

  • Save wilmoore/1b435441ee44491fa919b893885c7ebe to your computer and use it in GitHub Desktop.

Select an option

Save wilmoore/1b435441ee44491fa919b893885c7ebe to your computer and use it in GitHub Desktop.
Software Engineering :: Web :: Browser :: Extension :: Development :: Add Calendar Event

Software Engineering :: Web :: Browser :: Extension :: Development :: Add Calendar Event

⪼ Made with 💜 by Polyglot.

reference
related

Calendar Links

Template

https://www.google.com/calendar/render?action=TEMPLATE&text=Lunch%20Meeting&dates=20241031T120000Z/20241031T130000Z&details=Discussion%20on%20project%20progress&location=123%20Main%20St,%20City&trp=false

TypeScript

interface CalendarEvent {
  title: string;
  startDate: string; // Format: YYYYMMDDTHHmmssZ or YYYYMMDDTHHmmss for specific timezone
  endDate: string;   // Same format as startDate
  details?: string;
  location?: string;
  isBusy?: boolean;  // Show as busy
  sourceName?: string;
  sourceUrl?: string;
}

function createGoogleCalendarUrl(event: CalendarEvent): string {
  const baseParams = {
    action: 'TEMPLATE',
    text: event.title,
    dates: `${event.startDate}/${event.endDate}`,
    trp: event.isBusy ? 'true' : 'false',
  };

  const optionalParams = {
    details: event.details,
    location: event.location,
    'sprop=name': event.sourceName,
    'sprop=website': event.sourceUrl,
  };

  // Use reduce to filter out undefined or empty parameters
  const filteredParams = Object.entries({...baseParams, ...optionalParams}).reduce((acc, [key, value]) => {
    if (value) {
      acc.set(key, value);
    }
    return acc;
  }, new URLSearchParams());

  // Create the URL and append the filtered search parameters
  const url = new URL('https://www.google.com/calendar/render');
  url.search = filteredParams.toString();

  return url.toString();
}

// Example usage
const eventUrl = createGoogleCalendarUrl({
  title: 'Team Meeting',
  startDate: '20241031T090000Z',
  endDate: '20241031T100000Z',
  details: 'Monthly strategy meeting',
  location: 'Conference Room 1',
  isBusy: true,
});

console.log(eventUrl);

Email Message (rendered)

Mark Mckellar <mark@amazonfbaaccelerator.com>
Apr 10, 2024, 7:19 PM (5 hours ago)
to wil.moore

Wil,

Congratulations, your call is scheduled!  Please be in a quiet place and provide enough time for the full call.

Here are the call details:
April 11, 2024
2:45 PM MDT

We'll be meeting here: https://us06web.zoom.us/j/81745116603 

Also - I just sent you a friend request on Facebook, did you see it?
If not, please add me with this link to my personal account 🙂

You can add the appointment to your calendar here:  
Google Calendar: https://msgsndr.com/google/calendar/add-event/hAv6zayep5V5QxPUhtDN
iCal/Outlook:
https://msgsndr.com/google/calendar/get-ics/hAv6zayep5V5QxPUhtDN

If you need to cancel please give 2 hours notice and click here:  https://msgsndr.com/widget/cancel-booking?event_id=hAv6zayep5V5QxPUhtDN

If you'd like to reschedule you can by clicking here:  https://msgsndr.com/widget/booking/66QCGpFbkNZ5pFeX4Snl?event_id=hAv6zayep5V5QxPUhtDN

I look forward to speaking with you soon!

-Mark Mckellar

Email Message (source)

<div style=3D"font-family: Roboto, Arial; font-size: 14px;"><p style=3D"mar=
gin:0px">Wil,<br><br>Congratulations, your call is scheduled!&nbsp; Please =
be in a quiet place and provide enough time for the full call.<br><br>Here =
are the call details:</p><p style=3D"margin:0px">April 11, 2024<br>2:45 PM =
MDT<br><br>We'll be meeting here: <a target=3D"_blank" href=3D"https://send=
-link.email/v1/smtp_email/event/clicked/message/eyJhbGciOiJIUzI1NiIsInR5cCI=
6IkpXVCJ9.eyJtZXNzYWdlSWQiOiJ3emZPYVQyaVZVRXFzYXB0aHMwOCIsInVybCI6Imh0dHBzJ=
TNBJTJGJTJGdXMwNndlYi56b29tLnVzJTJGaiUyRjgxNzQ1MTE2NjAzIiwiaG9zdCI6Imh0dHBz=
Oi8vc2VuZC1saW5rLmVtYWlsIiwiaWF0IjoxNzEyNzk4MzYyNTUzfQ.ID17uK0JqCp9_DYj_-DL=
hV_303KeOmOBNG4NjmKiEfQ">https://us06web.zoom.us/j/81745116603</a>&nbsp;</p=
><br/><p style=3D"margin:0px">Also - I just sent you a friend request on Fa=
cebook, did you see it?<br>If not, please <a target=3D"_blank" title=3D"add=
 me with this link to my personal account" href=3D"https://send-link.email/=
v1/smtp_email/event/clicked/message/eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.ey=
JtZXNzYWdlSWQiOiJ3emZPYVQyaVZVRXFzYXB0aHMwOCIsInVybCI6Imh0dHBzJTNBJTJGJTJGd=
3d3LmZhY2Vib29rLmNvbSUyRm1hcmsubWNrZWxsYXIiLCJob3N0IjoiaHR0cHM6Ly9zZW5kLWxp=
bmsuZW1haWwiLCJpYXQiOjE3MTI3OTgzNjI1NTN9.bQlPZh5nj5ZLlL-RBQwDyhZPsbo3fuJNGf=
MbSGlO7qo">add me with this link to my personal account</a> =F0=9F=99=82<br=
><br>You can add the appointment to your calendar here:&nbsp;&nbsp;<br>Goog=
le Calendar: <a target=3D"_blank" href=3D"https://send-link.email/v1/smtp_e=
mail/event/clicked/message/eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJtZXNzYWd=
lSWQiOiJ3emZPYVQyaVZVRXFzYXB0aHMwOCIsInVybCI6Imh0dHBzJTNBJTJGJTJGbXNnc25kci=
5jb20lMkZnb29nbGUlMkZjYWxlbmRhciUyRmFkZC1ldmVudCUyRmhBdjZ6YXllcDVWNVF4UFVod=
EROIiwiaG9zdCI6Imh0dHBzOi8vc2VuZC1saW5rLmVtYWlsIiwiaWF0IjoxNzEyNzk4MzYyNTUz=
fQ.iUgQlt4epCtljplHzAARASEAFB1PQUMB8Ni5cXuau7c">https://msgsndr.com/google/=
calendar/add-event/hAv6zayep5V5QxPUhtDN</a><br>iCal/Outlook:<br><a target=
=3D"_blank" href=3D"https://send-link.email/v1/smtp_email/event/clicked/mes=
sage/eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJtZXNzYWdlSWQiOiJ3emZPYVQyaVZVR=
XFzYXB0aHMwOCIsInVybCI6Imh0dHBzJTNBJTJGJTJGbXNnc25kci5jb20lMkZnb29nbGUlMkZj=
YWxlbmRhciUyRmdldC1pY3MlMkZoQXY2emF5ZXA1VjVReFBVaHRETiIsImhvc3QiOiJodHRwczo=
vL3NlbmQtbGluay5lbWFpbCIsImlhdCI6MTcxMjc5ODM2MjU1M30.tHibNEFqOSuGziuxNn_SVo=
sd8SZJzK2thn5KM6vLpwU">https://msgsndr.com/google/calendar/get-ics/hAv6zaye=
p5V5QxPUhtDN</a><br><br><em>If you need to cancel please give 2 hours notic=
e and click here:&nbsp; </em><a target=3D"_blank" href=3D"https://send-link=
.email/v1/smtp_email/event/clicked/message/eyJhbGciOiJIUzI1NiIsInR5cCI6IkpX=
VCJ9.eyJtZXNzYWdlSWQiOiJ3emZPYVQyaVZVRXFzYXB0aHMwOCIsInVybCI6Imh0dHBzJTNBJT=
JGJTJGbXNnc25kci5jb20lMkZ3aWRnZXQlMkZjYW5jZWwtYm9va2luZyUzRmV2ZW50X2lkJTNEa=
EF2NnpheWVwNVY1UXhQVWh0RE4iLCJob3N0IjoiaHR0cHM6Ly9zZW5kLWxpbmsuZW1haWwiLCJp=
YXQiOjE3MTI3OTgzNjI1NTN9.1hAaRI5VoPzz4jUHcrr8JDi-Q0BOTUvnt6euSxvBLYg"><em>h=
ttps://msgsndr.com/widget/cancel-booking?event_id=3DhAv6zayep5V5QxPUhtDN</e=
m></a><br><br><em>If you'd like to reschedule you can by clicking here:&nbs=
p; </em><a target=3D"_blank" href=3D"https://send-link.email/v1/smtp_email/=
event/clicked/message/eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJtZXNzYWdlSWQi=
OiJ3emZPYVQyaVZVRXFzYXB0aHMwOCIsInVybCI6Imh0dHBzJTNBJTJGJTJGbXNnc25kci5jb20=
lMkZ3aWRnZXQlMkZib29raW5nJTJGNjZRQ0dwRmJrTlo1cEZlWDRTbmwlM0ZldmVudF9pZCUzRG=
hBdjZ6YXllcDVWNVF4UFVodEROIiwiaG9zdCI6Imh0dHBzOi8vc2VuZC1saW5rLmVtYWlsIiwia=
WF0IjoxNzEyNzk4MzYyNTUzfQ.j9w4Jf0M0EspBpzT2aNxYyLc-X4Jb5aukQATzfdfHJM"><em>=
https://msgsndr.com/widget/booking/66QCGpFbkNZ5pFeX4Snl?event_id=3DhAv6zaye=
p5V5QxPUhtDN</em></a><em><br><br></em>I look forward to speaking with you s=
oon!<br><br>-Mark Mckellar </p></div><img src=3D"https://send-link.email/v1=
/smtp_email/event/opened/message/eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJtZ=
XNzYWdlSWQiOiJ3emZPYVQyaVZVRXFzYXB0aHMwOCIsImhvc3QiOiJodHRwczovL3NlbmQtbGlu=
ay5lbWFpbCIsImlhdCI6MTcxMjc5ODM2MjU1M30.nMLADJg_MmMV5wEnwVbciz7VIW_TjQhH5G3=
CmE_p6Q4" height=3D"1px" width=3D"1px" alt=3D"" style=3D"display: none;" />

Code To Identify an Email as including meeting details

function extractMeetingDetails(emailHtml) {
  // Define a regex pattern to identify the date and time
  const dateTimePattern = /(\bJanuary|\bFebruary|\bMarch|\bApril|\bMay|\bJune|\bJuly|\bAugust|\bSeptember|\bOctober|\bNovember|\bDecember)\s\d{1,2},\s\d{4}<br>\d{1,2}:\d{2}\s(AM|PM)\s\w{3}/g;

  // Define keywords that suggest a meeting link or location
  const meetingKeywords = ['meeting here:', 'call details:', 'Google Calendar:', 'iCal/Outlook:', 'zoom.us'];

  // Search the email for the date and time pattern
  const dateTimeMatches = emailHtml.match(dateTimePattern);

  // Search the email for meeting keywords
  const hasMeetingKeywords = meetingKeywords.some(keyword => emailHtml.includes(keyword));

  // If both a date/time and any meeting keywords are found, assume this is a meeting email
  if (dateTimeMatches && hasMeetingKeywords) {
    return {
      isMeeting: true,
      details: {
        dateTime: dateTimeMatches[0],
        link: extractMeetingLink(emailHtml)
      }
    };
  } else {
    return { isMeeting: false };
  }
}

// Helper function to extract meeting link (this can be tailored to specific formats)
function extractMeetingLink(emailHtml) {
  // Look for common meeting URLs, e.g., Zoom
  const linkPattern = /https?:\/\/[\w.-]+\/(j|my)\/\d+/g;
  const match = emailHtml.match(linkPattern);
  return match ? match[0] : 'No link found';
}

// Example usage with the email HTML as a string
const emailHtml = `...`; // Your email HTML content here

const meetingDetails = extractMeetingDetails(emailHtml);

if (meetingDetails.isMeeting) {
  console.log("Meeting detected!", meetingDetails.details);
} else {
  console.log("This does not seem to be a meeting.");
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment