1

如果我在网上搜索“带有 Google 日历的 Notion API”之类的内容,我只会找到与 Automate.io 或 Zappier 相关的解决方案。

有没有办法使用这些强大的 API 将 Notion 与 Google 日历集成,而不依赖于这些站点?我可以使用哪种编程语言来做到这一点?我需要一个服务器来定期运行程序吗?

PS:在 YT 上我发现了一些 Python 的东西,但我找不到使用这些工具的完整指南

4

1 回答 1

3

我可以使用哪种编程语言来做到这一点?

您可以轻松地使用Google App ScriptNotion API来实现这一点。Google 应用脚本的语法基于 javascript(尽管不支持某些 ES6 功能)。使用CalendarApp,您几乎可以控制 Google 日历上的所有内容。

我需要一个服务器来定期运行程序吗?

不,你不需要。在 Google App Script 中,您可以添加时间驱动的触发器以使其自动启动。

这是一个将概念同步到日历的简单示例:

使用 UrlFetchApp 将查询发布到您的 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.idanddatabase_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来搜索已经同步的页面

这里继续第一步的主要功能。

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 或 Google App Script 工程师,这些代码可能还需要改进,希望对你有用。

于 2021-05-30T04:07:41.813 回答