Plugin: Agenda Notes

name

Agenda Notes

description

A plugin that syncs your google calendar with amplenote to create meeting and appointments notes with backlinks to all the attendees.

- How to setup -

1. Go to the settings of calendar app of your choice and copy the private icsn link of the calendar. For the demonstration I'll be using google calendar



2. Go to account settings



3. From the sidebar click on "plugins". Search for agenda notes plugin and go to settings.



4. Paste in the private icsn link copied in the first step.


- How to use -

Open any note, click on the three dots and select "agenda notes" plugin from the dropdown.

Contact - @Capta1nCool on discord.

icon

event

setting

calendar_url


linkCode

{
async noteOption(app, noteUUID) {
const markdown = await app.getNoteContent({ uuid: noteUUID })
let output = 'Agenda: \n'
 
const calendar_url = app.settings["calendar_url"]
await this._loadLib("https://cdnjs.cloudflare.com/ajax/libs/ical.js/0.0.3/ical.min.js")
 
let events = await this.getTodayEvents(calendar_url)
 
for (const event of events) {
let note_content = 'Attendees: \n';
for (const i in event.attendees) {
const uuid = await app.createNote(event.attendees[i], [ "agenda/attendee" ]);
note_content += `[${event.attendees[i]}](https://www.amplenote.com/notes/${uuid})\n`
}
const uuid = await app.createNote(event.summary, [ "agenda/notes" ]);
await app.replaceNoteContent({ uuid: uuid }, note_content);
 
 
const startTime = new Date(event.start).toLocaleTimeString("en-US", {
hour: "2-digit",
minute: "2-digit",
});
 
const endTime = event.end
? new Date(event.end).toLocaleTimeString("en-US", {
hour: "2-digit",
minute: "2-digit",
})
: "No end time";
 
output += `${startTime} - ${endTime} [${event.summary}](https://www.amplenote.com/notes/${uuid})\n`;
}
 
await app.replaceNoteContent({ uuid: noteUUID }, output + '\n' + markdown);
},
 
async getTodayEvents(secretAddress) {
try {
const response = await fetch(`https://amplenote-plugins-cors-anywhere.onrender.com/${secretAddress}`);
if (!response.ok) {
throw new Error(`Failed to fetch ICS file: ${response.statusText}`);
}
 
const icsData = await response.text();
 
// Parse the ICS file
const jcalData = ICAL.parse(icsData);
const calendar = jcalData[1][2];
 
const today = new Date();
const todayDateString = today.toISOString().split("T")[0];
 
const todayEvents = [];
 
for (const item of calendar) {
if (item[0] === "vevent") {
const properties = item[1];
const dtstart = properties.find((prop) => prop[0] === "dtstart");
const dtend = properties.find((prop) => prop[0] === "dtend");
const summary = properties.find((prop) => prop[0] === "summary");
const attendees = properties
.filter((prop) => prop[0] === "attendee")
.map((attendee) => attendee[3].replace(/^mailto:/, ""));
 
 
if (dtstart) {
const eventDate = dtstart[3]; // Get the start date
const isAllDay = dtstart[1]?.date;
 
// Normalize all-day events to just the date part
const startDate = isAllDay ? eventDate : new Date(eventDate).toISOString().split("T")[0];
 
// Check if the event occurs today
if (startDate === todayDateString) {
todayEvents.push({
summary: summary ? summary[3] : "No Title",
start: dtstart[3],
end: dtend ? dtend[3] : null,
attendees: attendees.length ? attendees : "No attendees",
});
}
}
}
}
 
return todayEvents;
 
} catch (error) {
console.error("Error fetching or parsing ICS file:", error);
return [];
}
},
 
isToday(unixTimestamp) {
const date = new Date(unixTimestamp * 1000); // Convert from seconds to milliseconds
 
const today = new Date();
 
return (
date.getFullYear() === today.getFullYear() &&
date.getMonth() === today.getMonth() &&
date.getDate() === today.getDate()
);
},
 
_loadLib(url) {
if (this._haveLoadedRecordRTC) return Promise.resolve(true);
 
return new Promise(function(resolve) {
const script = document.createElement("script");
script.setAttribute("type", "text/javascript");
script.setAttribute("src", url);
script.addEventListener("load", function() {
this._haveLoadedRecordRTC = true;
resolve(true);
});
document.body.appendChild(script);
});
}
}