【问题标题】:Notion APIs with Google Calendar带有 Google 日历的 Notion API
【发布时间】:2021-08-17 12:22:08
【问题描述】:

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

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

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

【问题讨论】:

    标签: python api google-calendar-api notion-api


    【解决方案1】:

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

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

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

    不,你不需要。在 Google App Script 中,您可以添加 time-driven triggers 让它自动启动。

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

    使用 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
    }
    

    创建一个新的日历事件

    pageresponse.results 数组之一。这里我们使用page.iddatabase_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);
        }
    }
    

    Full example code

    我不是专业的 javascript 或 Google App Script 工程师,这些代码可能还需要改进,希望对你有用。

    【讨论】:

      猜你喜欢
      • 2018-08-28
      • 1970-01-01
      • 2022-01-11
      • 1970-01-01
      • 2018-03-06
      • 2021-08-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多