带有 Google 日历的概念 API
Notion APIs with Google Calendar
如果我在网上搜索“Notion API with Google Calendar”,我只能找到与 Automate.io 或 Zappier 相关的解决方案。
有没有办法使用这些强大的 API 将 Notion 与 Google Calendar 集成,而不 依赖那些网站?
我可以使用哪种编程语言来做到这一点?我需要服务器定期 运行 程序吗?
PS:在 YT 上,我找到了 Python 的东西,但我找不到使用这些工具的完整指南
我可以使用哪种编程语言来做到这一点?
您可以轻松使用 Google App Script and Notion API to achieve this. The syntax of Google app script is based on javascript (although some ES6 features are not supported). With the CalendarApp,您几乎可以控制 Google 日历上的所有内容。
我需要一个服务器来定期 运行 程序吗?
不,你不需要。在Google App Script中,您可以添加time-driven triggers让它自动启动。
这是一个将概念同步到日历的简单示例:
使用 UrlFetchApp post 查询您的 Notion 数据库
在这种情况下,我将根据'DeadLine' 属性设置事件的日期。所以我附加了一个过滤器来排除空值。
function main() {
let data = {
"filter": {
"property": "DeadLine",
"date": {
"is_not_empty": true
}
}
};
let options = {
'method': 'post',
'contentType': 'application/json',
'headers': {
Authorization: 'Bearer ' + 'your integration token',
'Notion-Version': '2021-05-13',
'Content-Type': 'application/json',
},
'payload': JSON.stringify(data)
};
let response = UrlFetchApp.fetch('https://api.notion.com/v1/databases/your_database_id/query', options);
response = JSON.parse(response.getContentText());
//other code
}
创建新的日历事件
page
是 response.results
数组之一。这里我们使用page.id
和database_id
作为事件的唯一标识符。并且需要区分deadline是包含时间还是只包含日期。
这里要处理两个变量:
- 是否有结束日期
- 有时间或只有约会
const calendar = CalendarApp.getCalendarById("your calendar id");
const onlyDateRegex = /(\d{4})-(\d{2})-(\d{2})\b/;
const dateTimeRegex = /(\d{4})-(\d{2})-(\d{2})T(\d{2})\:(\d{2})\:(\d{2})\.(\d{3})\+(\d{2})\:(\d{2})\b/;
function create(page) {
let deadLine = page.properties.DeadLine;
let title = "";
page.properties.Name.title.forEach((rich_text) => {
title += rich_text.plain_text;
})
let pageId = page.id + " in database " + page.parent.database_id;
let startDate = deadLine.date.start;
let endDate = deadLine.date.end;
let startDateObj = new Date(startDate);
let endDateObj = new Date(endDate);
let evnet;
Logger.log("Create page " + title);
if (deadLine.date.end !== null) {
if (onlyDateRegex.test(startDate))
evnet = calendar.createAllDayEvent(title, startDateObj, endDateObj);
if (dateTimeRegex.test(startDate))
evnet = calendar.createEvent(title, startDateObj, endDateObj);
} else {
if (onlyDateRegex.test(startDate))
evnet = calendar.createAllDayEvent(title, startDateObj);
if (dateTimeRegex.test(startDate))
evnet = calendar.createEvent(title, startDateObj, startDateObj);
}
evnet.setDescription(pageId);
}
然后我们可以通过描述中的id来搜索已经同步的页面
这里继续第一步的main函数
function main() {
//other code
response = JSON.parse(response.getContentText());
for (let i = 0; i < response.results.length; i++) {
let pageId = response.results[i].id + " in database " + response.results[i].parent.database_id;
let event = search(pageId);
if (event === null) create(response.results[i]);
else update(event, response.results[i]);
}
}
function search(str) {
let events = calendar.getEvents(new Date("1970-1-1"), new Date("2100-1-1"), {
search: str
});
if (events.length > 1) throw new Error("uuid duplicate in search");
if (events.length === 0) return null;
return events[0];
}
如果没有找到结果,创建一个新事件,否则,尝试更新它。
更新事件的做法与创建时几乎相同
function update(event, page) {
let deadLine = page.properties.DeadLine;
let title = "";
page.properties.Name.title.forEach((rich_text) => {
title += rich_text.plain_text;
})
Logger.log("Update page " + title);
let startDate = deadLine.date.start;
let endDate = deadLine.date.end;
let startDateObj = new Date(startDate);
let endDateObj = new Date(endDate);
if (deadLine.date.end !== null) {
if (onlyDateRegex.test(startDate)) {
startDateObj.setHours(0, 0, 0, 0);
endDateObj.setHours(0, 0, 0, 0);
if (event.isAllDayEvent()) {
if ((event.getAllDayStartDate().getTime() !== startDateObj.getTime()) ||
(event.getAllDayEndDate().getTime() !== endDateObj.getTime())) {
Logger.log("update allDayStartDate " + event.getAllDayStartDate() + " to " + startDateObj);
Logger.log("update allDayEndDate " + event.getAllDayEndDate() + " to " + endDateObj);
event.setAllDayDates(startDateObj, endDateObj);
}
} else event.setAllDayDates(startDateObj, endDateObj);
}
if (dateTimeRegex.test(startDate)) {
if (event.isAllDayEvent()) {
Logger.log("change to dateTime, start: " + startDateObj + " end: " + endDateObj);
event.setTime(startDateObj, endDateObj);
} else {
if ((event.getStartTime().getTime() !== startDateObj.getTime()) ||
(event.getEndTime().getTime() !== endDateObj.getTime())) {
Logger.log("update dateTime, start: " + startDateObj + " end: " + endDateObj);
event.setTime(startDateObj, endDateObj);
}
}
}
} else {
if (onlyDateRegex.test(startDate)) {
startDateObj.setHours(0, 0, 0, 0);
if (event.isAllDayEvent()) {
if ((event.getAllDayStartDate().getTime() !== startDateObj.getTime()) ||
(event.getAllDayEndDate().getTime() !== startDateObj.getTime())) {
Logger.log("update allOneDayDate " + event.getAllDayStartDate() + " to " + startDateObj);
event.setAllDayDate(startDateObj);
}
} else {
Logger.log("change to allOneDayDate: " + startDateObj);
event.setAllDayDates(startDateObj);
}
}
if (dateTimeRegex.test(startDate)) {
if (event.isAllDayEvent()) {
Logger.log("change to dateTime: " + startDateObj);
event.setTime(startDateObj, startDateObj);
} else {
if (event.getStartTime().getTime() !== startDateObj.getTime()) {
Logger.log("update dateTime: " + startDateObj);
event.setTime(startDateObj, startDateObj);
}
}
}
}
if (event.getTitle() !== title) {
Logger.log("update title: \"" + event.getTitle() + "\" to " + title);
event.setTitle(title);
}
}
我不是专业的javascript或GoogleApp Script工程师,这些代码可能还需要改进,希望有用。
如果我在网上搜索“Notion API with Google Calendar”,我只能找到与 Automate.io 或 Zappier 相关的解决方案。
有没有办法使用这些强大的 API 将 Notion 与 Google Calendar 集成,而不 依赖那些网站? 我可以使用哪种编程语言来做到这一点?我需要服务器定期 运行 程序吗?
PS:在 YT 上,我找到了 Python 的东西,但我找不到使用这些工具的完整指南
我可以使用哪种编程语言来做到这一点?
您可以轻松使用 Google App Script and Notion API to achieve this. The syntax of Google app script is based on javascript (although some ES6 features are not supported). With the CalendarApp,您几乎可以控制 Google 日历上的所有内容。
我需要一个服务器来定期 运行 程序吗?
不,你不需要。在Google App Script中,您可以添加time-driven triggers让它自动启动。
这是一个将概念同步到日历的简单示例:
使用 UrlFetchApp post 查询您的 Notion 数据库
在这种情况下,我将根据'DeadLine' 属性设置事件的日期。所以我附加了一个过滤器来排除空值。
function main() {
let data = {
"filter": {
"property": "DeadLine",
"date": {
"is_not_empty": true
}
}
};
let options = {
'method': 'post',
'contentType': 'application/json',
'headers': {
Authorization: 'Bearer ' + 'your integration token',
'Notion-Version': '2021-05-13',
'Content-Type': 'application/json',
},
'payload': JSON.stringify(data)
};
let response = UrlFetchApp.fetch('https://api.notion.com/v1/databases/your_database_id/query', options);
response = JSON.parse(response.getContentText());
//other code
}
创建新的日历事件
page
是 response.results
数组之一。这里我们使用page.id
和database_id
作为事件的唯一标识符。并且需要区分deadline是包含时间还是只包含日期。
这里要处理两个变量:
- 是否有结束日期
- 有时间或只有约会
const calendar = CalendarApp.getCalendarById("your calendar id");
const onlyDateRegex = /(\d{4})-(\d{2})-(\d{2})\b/;
const dateTimeRegex = /(\d{4})-(\d{2})-(\d{2})T(\d{2})\:(\d{2})\:(\d{2})\.(\d{3})\+(\d{2})\:(\d{2})\b/;
function create(page) {
let deadLine = page.properties.DeadLine;
let title = "";
page.properties.Name.title.forEach((rich_text) => {
title += rich_text.plain_text;
})
let pageId = page.id + " in database " + page.parent.database_id;
let startDate = deadLine.date.start;
let endDate = deadLine.date.end;
let startDateObj = new Date(startDate);
let endDateObj = new Date(endDate);
let evnet;
Logger.log("Create page " + title);
if (deadLine.date.end !== null) {
if (onlyDateRegex.test(startDate))
evnet = calendar.createAllDayEvent(title, startDateObj, endDateObj);
if (dateTimeRegex.test(startDate))
evnet = calendar.createEvent(title, startDateObj, endDateObj);
} else {
if (onlyDateRegex.test(startDate))
evnet = calendar.createAllDayEvent(title, startDateObj);
if (dateTimeRegex.test(startDate))
evnet = calendar.createEvent(title, startDateObj, startDateObj);
}
evnet.setDescription(pageId);
}
然后我们可以通过描述中的id来搜索已经同步的页面
这里继续第一步的main函数
function main() {
//other code
response = JSON.parse(response.getContentText());
for (let i = 0; i < response.results.length; i++) {
let pageId = response.results[i].id + " in database " + response.results[i].parent.database_id;
let event = search(pageId);
if (event === null) create(response.results[i]);
else update(event, response.results[i]);
}
}
function search(str) {
let events = calendar.getEvents(new Date("1970-1-1"), new Date("2100-1-1"), {
search: str
});
if (events.length > 1) throw new Error("uuid duplicate in search");
if (events.length === 0) return null;
return events[0];
}
如果没有找到结果,创建一个新事件,否则,尝试更新它。
更新事件的做法与创建时几乎相同
function update(event, page) {
let deadLine = page.properties.DeadLine;
let title = "";
page.properties.Name.title.forEach((rich_text) => {
title += rich_text.plain_text;
})
Logger.log("Update page " + title);
let startDate = deadLine.date.start;
let endDate = deadLine.date.end;
let startDateObj = new Date(startDate);
let endDateObj = new Date(endDate);
if (deadLine.date.end !== null) {
if (onlyDateRegex.test(startDate)) {
startDateObj.setHours(0, 0, 0, 0);
endDateObj.setHours(0, 0, 0, 0);
if (event.isAllDayEvent()) {
if ((event.getAllDayStartDate().getTime() !== startDateObj.getTime()) ||
(event.getAllDayEndDate().getTime() !== endDateObj.getTime())) {
Logger.log("update allDayStartDate " + event.getAllDayStartDate() + " to " + startDateObj);
Logger.log("update allDayEndDate " + event.getAllDayEndDate() + " to " + endDateObj);
event.setAllDayDates(startDateObj, endDateObj);
}
} else event.setAllDayDates(startDateObj, endDateObj);
}
if (dateTimeRegex.test(startDate)) {
if (event.isAllDayEvent()) {
Logger.log("change to dateTime, start: " + startDateObj + " end: " + endDateObj);
event.setTime(startDateObj, endDateObj);
} else {
if ((event.getStartTime().getTime() !== startDateObj.getTime()) ||
(event.getEndTime().getTime() !== endDateObj.getTime())) {
Logger.log("update dateTime, start: " + startDateObj + " end: " + endDateObj);
event.setTime(startDateObj, endDateObj);
}
}
}
} else {
if (onlyDateRegex.test(startDate)) {
startDateObj.setHours(0, 0, 0, 0);
if (event.isAllDayEvent()) {
if ((event.getAllDayStartDate().getTime() !== startDateObj.getTime()) ||
(event.getAllDayEndDate().getTime() !== startDateObj.getTime())) {
Logger.log("update allOneDayDate " + event.getAllDayStartDate() + " to " + startDateObj);
event.setAllDayDate(startDateObj);
}
} else {
Logger.log("change to allOneDayDate: " + startDateObj);
event.setAllDayDates(startDateObj);
}
}
if (dateTimeRegex.test(startDate)) {
if (event.isAllDayEvent()) {
Logger.log("change to dateTime: " + startDateObj);
event.setTime(startDateObj, startDateObj);
} else {
if (event.getStartTime().getTime() !== startDateObj.getTime()) {
Logger.log("update dateTime: " + startDateObj);
event.setTime(startDateObj, startDateObj);
}
}
}
}
if (event.getTitle() !== title) {
Logger.log("update title: \"" + event.getTitle() + "\" to " + title);
event.setTitle(title);
}
}
我不是专业的javascript或GoogleApp Script工程师,这些代码可能还需要改进,希望有用。