带有 Google 日历的 Notion API

Posted

技术标签:

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

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

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

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

【问题讨论】:

【参考方案1】:

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

您可以轻松地使用Google App Script 和Notion 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 = /(\d4)-(\d2)-(\d2)\b/;
const dateTimeRegex = /(\d4)-(\d2)-(\d2)T(\d2)\:(\d2)\:(\d2)\.(\d3)\+(\d2)\:(\d2)\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 工程师,这些代码可能还需要改进,希望对你有用。

【讨论】:

以上是关于带有 Google 日历的 Notion API的主要内容,如果未能解决你的问题,请参考以下文章

带有 Google 日历 API(时隙)React/NodeJS 的预约系统

使用 API 从 Google 日历中检索事件

谷歌日历API v3从timeMin之前的全天活动

Google Calendar API 事件空闲/忙碌/阻塞数据

如何在没有用户身份验证的情况下列出 Google 日历活动

Google Calendar API,如何添加带有附加新生成的google meet的事件?