Skip to content

Instantly share code, notes, and snippets.

@zhgchgli0718
Created March 10, 2024 06:49
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save zhgchgli0718/400143b05a09c3e7a6bad23a78f5ac5f to your computer and use it in GitHub Desktop.
Save zhgchgli0718/400143b05a09c3e7a6bad23a78f5ac5f to your computer and use it in GitHub Desktop.
[POC] Notion Database to Calendar (.ics)
// Constant variables
const notionToken = "XXXXX";
const safeToken = "XXXXX";
function doGet(e) {
const ics = HtmlService.createTemplateFromFile('ics');
if (e.parameter.token != safeToken) {
return ContentService.createTextOutput("Access Denied!");
}
ics.events = getQuickNote();
return ContentService.createTextOutput(ics.evaluate().getContent()).setMimeType(ContentService.MimeType.ICAL);
}
function debug() {
const ics = HtmlService.createTemplateFromFile('ics');
ics.events = getQuickNote();
Logger.log(ics.evaluate().getContent());
}
function getQuickNote() {
// YOUR FILTER Condition:
const payload = {
"filter": {
"and": [
{
"property": "Date",
"date": {
"is_not_empty": true
}
}
,
{
"property": "Name",
"title": {
"is_not_empty": true
}
}
]
}
};
const result = getDatabase(YOUR_DATABASE_ID, payload);
var events = [];
for (const index in result.results) {
const item = result.results[index]
const properties = item.properties;
const id = item['id'];
const create = toICSDate(item["created_time"]);
const edit = toICSDate(item["last_edited_time"]);
const startDate = properties['Date']['date']['start'];
const start = toICSDate(startDate);
var endDate = properties['Date']?.['date']?.['end'];
if (endDate == null) {
endDate = startDate;
}
const end = toICSDate(endDate);
const type = properties['Type']?.['multi_select']?.[0]?.['name'];
const title = "["+type+"] "+properties?.['Name']?.['title']?.[0]?.['plain_text'];
const description = item['url'];
events.push(
{
"id":id,
"create":create,
"edit":edit,
"start":start,
"end":end,
"title":title,
"description":description
}
)
}
return events;
}
// TO UTC Date
function toICSDate(date) {
const icsDate = new Date(date);
icsDate.setHours(icsDate.getHours() - 8);
return Utilities.formatDate(icsDate, "GMT+8", "yyyyMMdd'T'HHmmss'Z'");// 20240304T132300Z
}
// Notion
function getDatabase(id, payload) {
const url = 'https://api.notion.com/v1/databases/'+id+'/query/';
const options = {
method: 'post',
headers: {
'Authorization': 'Bearer '+notionToken,
'Content-Type': 'application/json',
'Notion-Version': '2022-06-28'
},
payload: JSON.stringify(payload)
};
const result = UrlFetchApp.fetch(url, options);
return JSON.parse(result.getContentText());
}
BEGIN:VCALENDAR
PRODID:-//Google Inc//Google Calendar 70.9054//EN
VERSION:2.0
CALSCALE:GREGORIAN
METHOD:PUBLISH
X-WR-CALNAME:NotionCalendar
X-WR-TIMEZONE:Asia/Taipei
BEGIN:VTIMEZONE
TZID:Asia/Taipei
X-LIC-LOCATION:Asia/Taipei
BEGIN:STANDARD
TZOFFSETFROM:+0800
TZOFFSETTO:+0800
TZNAME:CST
DTSTART:19700101T000000
END:STANDARD
END:VTIMEZONE
<?
for(const eventIndex in events) {
const event = events[eventIndex];
?>
BEGIN:VEVENT
DTSTART:<?=event["start"]?>
DTEND:<?=event["end"]?>
DTSTAMP:<?=event["edit"]?>
UID:<?=event["id"]?>
CREATED:<?=event["create"]?>
LAST-MODIFIED:<?=event["edit"]?>
SEQUENCE:0
STATUS:CONFIRMED
SUMMARY:<?=event["title"]?>
DESCRIPTION:<?=event["description"]?>
TRANSP:OPAQUE
END:VEVENT
<?
}
?>
END:VCALENDAR
@zhgchgli0718
Copy link
Author

image

image

@zhgchgli0718
Copy link
Author

image

image

@zhgchgli0718
Copy link
Author

p.s. 純 POC,程式碼邏輯、架構無暇優化,請單純參考此實現可能性

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment