Script to synchronize between a Notion database and Google Calendar both ways. Uses Google App Script.

Overview

Yet Another Two Way Notion-Google Calendar Sync Script

A script to sync events between Google calendar and a Notion database.

Features!

  • Google App Script based
    • Script hosted by Google
    • Trigger the scripts automatically with triggers
      • Time Intervals
      • GCal Updates
    • Logs that are saved and can be looked at later
  • Sync both from Google Calendar, and from Notion
    • Creation
    • Updates
      • Changing calendars from Notion
    • Deletions
  • Multi-calendar support
  • Support for recurring Events (Only available by setting through GCal)
  • No Notion formulas
  • Flexible property names
    • Can be modified easily in the code
  • Support for all day events, multi day events and scheduled events

For setup instructions and FAQ, please go to the wiki!

Known limitations/Bugs

  • Sync from Notion sometimes doesn't register when the page was recently updated by GCal
    • Caused by lack of precision in Notion's last edited timestamp
  • Will only check 100 most recently edited pages in database
    • Caused by Notion API limit
  • Rich text (bolding, italics, etc.) used in the description will be overwritten to plain text after syncing.
  • Doesn't seem to work with auto-generated calendars such as Birthdays. May be a limitation of GCal API. See #3
Comments
  • Hi! I've been using this script and it worked fine for the past month. But recently I've been getting this same error message:

    Hi! I've been using this script and it worked fine for the past month. But recently I've been getting this same error message:

        Hi! I've been using this script and it worked fine for the past month. But recently I've been getting this same error message:
    

    Error: API call to calendar.events.list failed with error: Sync token is no longer valid, a full sync is required. syncFromGCal @ main.js.gs:183 main @ main.js.gs:38

    I only have very rudimentary knowledge of coding, so I don't know how to perform this full sync. Hope you can assist!

    Originally posted by @hikarizun in https://github.com/hk21702/YA-GCal-Notion-Sync-Script/issues/3#issuecomment-1364506998

    info-needed 
    opened by hk21702 4
  • "Service invoked too many times" Error Message

    I have one of the triggers set up to be every 15 minutes. This worked fine up until yesterday when I swapped the code I used for a newer version. The it started failing and throwing errors. First this longer error:

    Error: Error trying to get page property Last Sync from page bcfa4608-1c6c-42df-bc74-eff395bfb0a6. Ensure that the database is setup correctly! EM: Service invoked too many times for one day: urlfetch.
        at getPageProperty(main:386:11)
        at isPageUpdatedRecently(main:753:24)
        at syncToGCal(main:60:9)
        at main(main:27:23)
    

    The after a few failed attempts it just went down to this:

    Exception: Service invoked too many times for one day: urlfetch.
        at notionFetch(main:408:32)
        at syncToGCal(main:53:25)
        at main(main:27:23)
    

    immediately after starting the sync to GCal.

    Is this a problem with Notion receiving to many requests or something else?

    opened by prossberg 4
  • Deleting event in Notion doesn't delete in GCal

    Deleting event in Notion doesn't delete in GCal

    I've tried deleting the event in Notion as well as Tagging the event as Cancelled/Removed. The event doesn't delete in Notion.

    However if I delete the event in GCal, it is deleted in Notion.

    bug 
    opened by tatelax 3
  • Whole-day event - offset by one day to get the end date

    Whole-day event - offset by one day to get the end date

    L497 Comment said offset by one day to get the end date. But the code seems to be missing, which leads to the problem of extending the days of whole-day events on GCal after synchronization.

    bug documentation 
    opened by sykin13 3
  • Problem with custom Notion domain

    Problem with custom Notion domain

    Hi. I was trying to setup this sync but I got an error.

    Error: {"object":"error","status":400,"code":"invalid_request_url","message":"Invalid request URL."}
    notionFetch	        @ main.gs:421
    deleteCancelledEvents	@ main.gs:704
    main	                @ main.gs:24
    

    I realized the function parseNotionProperties() is not getting DATABASE_ID as expected (workspace-domain/database-id instead of database-id). I am using a custom domain with a hyphen, in case it is relevant to the regex. I manually changed the DATABASE_ID value and it worked fine.

    bug info-needed 
    opened by EstebanMunoz 2
  • Can't complete a full sync due to error

    Can't complete a full sync due to error

    I get this error when trying to do a full sync. I think the script messes up when there are things written in the Location, Description or Calender field.

    Error: {"object":"error","status":400,"code":"validation_error","message":"Calendar is not a property that exists. Description is not a property that exists. Location is not a property that exists. Date is not a property that exists."}
    parseEvents	@ main.gs:252
    syncFromGCal	@ main.gs:175
    main	@ main.gs:32
    
    opened by prossberg 2
  • ALL DAY event won't sync from GCal

    ALL DAY event won't sync from GCal

    Hello a "all day" event will sync from Notion to GCal. But Won't Sync from GCal to Notion.

    The issue seems to be with "ISO8601" convertation.

    Please check the error I get:

    Error: {"object":"error","status":400,"code":"validation_error","message":"body failed validation: body.properties.Date.date.end should be a valid ISO 8601 date string, null, or undefined, instead was \"12/23/2022\"."}

    I would appreciate it if you could help me fix the problem. Thank you for your AMAZING script!

    bug 
    opened by barzoock 1
  • Include location data in new/updated events

    Include location data in new/updated events

    Tested and it works but updating a location property doesn't count as a recently modified page so to update location on an existing task, you would need to modify the body of the page.

    Fixes #30

    bug 
    opened by tatelax 1
  • "path.database_id should be a valid uuid"

    My DATABASE_ID begins with Calendar-. Notion API doesn't seem to like this.

    "Error: {"object":"error","status":400,"code":"validation_error","message":"path failed validation: path.database_id should be a valid uuid, instead was \"Calendar-c590d7c092bc48cb858038fc53e46760\"."}"

    If I hardcode the UUID into the URL, I get a new 404 error which says the database cannot be found.

    opened by tatelax 1
  • Use different tag as event name

    Use different tag as event name

    Hi, I'm using Notion as a calendar but because I'm a student I prefer to use the select tag as the identifier for my assignments. I don't use the default name tag at all so whenever I sync my database with my calendar the events say "untitled". Can I somehow change the code so that my select tag shows up as the name in Google calendar? image

    info-needed wontfix 
    opened by jobhasnofriends 1
  • Cannot read property 'end' of null

    Cannot read property 'end' of null

    Hi !

    Thanks to your reddit answer, I've fixed the date issues ! But now the script seem to have trouble with the "end" value. My basic knowledge of programing took a look, but couldn't find anything.

    Error	
    TypeError: Cannot read property 'end' of null
    convertToGCalEvent	@ main.gs:497
    syncToGCal	@ main.gs:53
    main	@ main.gs:25
    
    bug 
    opened by MrVallon412 1
  • Notion

    Notion "Rate limits" and Apps Script "timeout" won't allow to finish sync

    I'm trying to sync my Calendar with recurring dates. All the events in this calendar are recurring. There is a total of ~~45 events~~ 55 events that will recur annually, considering that each event will have a total of 30 copies ~~(so far is what the script sent)~~ there will be a total of 1650 pages. The problem is that there is this "Rate limit" that Notion has that you can find here :

    image

    Since I have to first do a FULL_SYNC to get all the events it will have A LOT of requests, so at some point, I will get this error:

    image

    I waited for the minutes it asks and ran the script again. Yet I found an issue, it will look for updates in every single event, even if the IGNORE_RECENTLY_PUSHED is turned on. I looked for the total of pages in the database and I have 1322, so I guess it is missing ~~only 28 of all the pages I need~~.

    image

    Any idea on how to solve this? I thought about setting a delay after the Rate limit has been reached, so it will wait a few minutes and after this time it will continue the script from where it stopped, yet this would also need to cancel the next time trigger, so it won't conflict.

    UPDATE:

    I've managed to solve the problem by deleting some events, cleaning all the database, and starting a fresh FULL_SYNC. Yet I'm facing another problem now. If I update too many events at once, I will get a TIMEOUT (30 minutes) of the Apps Script. Even if the Notion Rate Limit hasn't been reached, I get this TIMEOUT because the script has too many new entries to look at, it does get really big very easily. The script doesn't seem to continue from where it stopped, so it gets "stuck" because it will loop infinitely.

    Also, I've noticed some strange behaviors now, here is the list:

    • New recurring events (they are all annual) now will go till 2099, so I will have 77 pages for EACH individual event.
    • I had to delete some duplicated events, that were created after deleting and adding the exact same event even though I didn't recover it from the trash bin, (I had to delete to do the FULL_SYNC without reaching the Rate limit, so after doing it I added again all the events by creating new ones with the exact same settings). And when deleting those duplicated events the Apps Script console would say it couldn't find the Event ID even though there was an ID in the page.
    21 de nov. de 2022 04:02:26	Depuração	[-GCal] Deleting cancel tagged events from GCal
    21 de nov. de 2022 04:02:26	Depuração	[-GCal] Error. Page missing calendar id or event ID
    21 de nov. de 2022 04:02:26	Depuração	Archiving cancelled event.
    
    • Sometimes I will get this warning while the script is running:
    21 de nov. de 2022 04:11:23	Depuração	[+ND] Event found 3mamd7j3m44vqp9tsivt3dde9u_20321226 Fim da URSS (1991) (12/25/2032 -- 12/26/2032)
    21 de nov. de 2022 04:11:24	Depuração	Found multiple entries with event id 3mamd7j3m44vqp9tsivt3dde9u_20321226. This should not happen. Only considering index zero entry.
    21 de nov. de 2022 04:11:24	Depuração	[+ND] Event 3mamd7j3m44vqp9tsivt3dde9u_20321226 database page 8fb23e50-748e-4997-89e7-3fcd2bf4624b exists already. Attempting update.
    
    • Sometimes I will get this strange error:
    Error: <!DOCTYPE html>
    <html>
      <head>
        <meta charset="utf-8">
        <title>Notion</title>
        <style type="text/css">*{box-sizing:border-box}html{margin:0;padding:0}body{-webkit-font-smoothing:auto;align-items:center;background:#fffefc;color:#37352f;display:flex;flex-direction:column;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Helvetica,Apple Color Emoji,Arial,sans-serif,Segoe UI Emoji,Segoe UI Symbol;height:100vh;justify-content:center;justify-content:space-between;line-height:1.5;margin:0;padding:40px 20px;text-align:center}.top{height:40px}.details{align-items:flex-end;display:flex;font-size:13px;min-height:100px}.details h1{color:#999;display:inline-block;font-size:13px;margin:0 .75em}.details p{display:none}.details ul{color:#999;display:inline-block;margin:0;padding:0}.details li{display:inline-block;list-style:none;margin:0 .75em}.show-details-toggle{color:#999}.main{padding-bottom:20px}.main a{color:#37352f}a:hover{color:#e03e3e}@media screen and (max-width:960px){body{padding:20px}.details h1{margin-bottom:1em}.details h1,.details li{display:block}}</style>
        <script type="text/javascript">document.addEventListener("click",function(e){if(e.target.classList.contains("show-details-toggle")){e.preventDefault();var t=document.getElementsByClassName("show-details-toggle")[0],s=document.getElementsByClassName("details-expanded")[0];t.style.display="none",s.style.display="block"}},!1);</script>
      
    
    </head>
      <body>
        <div class="top"></div>
        <div class="main">
          <img
            alt="Notion"
            style="width: 40px; margin: 0 auto; display: block;"
            src="data:image/png;base64,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"
          />
          <p>
            Hmm... something’s not right<br />
            Please visit our
            <a target="_blank" href="https://status.notion.so/">status page</a>
            for more information.
          </p>
          <p>We’re working on it!</p>
        </div>
        <div class="details">
          <div class="details-collpased">
            <a href="#" class="show-details-toggle">Show error details</a>
          </div>
          <div style="display: none;" class="details-expanded">
            <div class="cf-error-details cf-error-504">
      <h1>Gateway time-out</h1>
      <p>The web server reported a gateway time-out error.</p>
      <ul>
        <li>Ray ID: 76d9f215ab63b17e</li>
        <li>Your IP address: 34.116.22.106</li>
        <li>Error reference number: 504</li>
        <li>Cloudflare Location: Atlanta</li>
      </ul>
    </div>
    
          </div>
        </div>
      </body>
    </html>
    
        at notionFetch(main:424:11)
        at getPageFromEvent(main:354:25)
        at parseEvents(main:222:27)
        at syncFromGCal(main:173:5)
        at main(main:32:5)
    
    info-needed stale 
    opened by astronaut954 4
  • Cannot add new calendar IDs without the process failing  (

    Cannot add new calendar IDs without the process failing ("API call to calendar.events.list failed with error: Sync token is no longer valid, a full sync is required.")

    Hello!

    I would like to use this script to sync between Notion and GCal however there are issues when I try to add a new calendar ID to CalendarID.js such as the script fails to execute once I add a new Calendar ID as the error "10:13:20 AM Error Error: API call to calendar.events.list failed with error: Sync token is no longer valid, a full sync is required.". I do not know how to patch this as I am not profficient in JS.

    Would it be possible for you to add me on discord as I would like help with another issue :P ether#9925

    The Stack Trace is

    Error: API call to calendar.events.list failed with error: Sync token is no longer valid, a full sync is required.
    syncFromGCal	@ main.gs:143
    main	@ main.gs:30
    

    The calendar ID constants is below

      /* Add calendars here. 
      The key (string before ':') is what you name the calendar. 
      The value (string after ':') is the calendar ID. 
      E.g. "My calendar name"]: "mycalendarid", */
      ["Primary"]: "primary",
      ["Birthdays"]: "addressbook#[email protected]",
    };
    
    
    bug help-wanted 
    opened by Etheride 5
Owner
kat
kat
chain-syncer is a module which allows you to synchronize your app with any ethereum-compatible blockchain/contract state. Fast. Realtime. Reliable.

Chain Syncer Chain Syncer is a JS module which allows you to synchronize your app with any ethereum-compatible blockchain/contract state. Fast. Realti

Miroslaw Shpak 10 Dec 15, 2022
Sync your personal calendar to your work calendar, privately 🐒

Callibella ?? It is considered unusual among Callibella in that it gives birth to only a single baby instead of twins, the norm for Callibella. Wikiep

Yo'av Moshe 19 Oct 12, 2022
Synchronize multiple Pi-hole instances

Orbital Sync Orbital Sync synchronizes multiple Pi-hole instances for high availability (HA) using the built-in "teleporter". In other words, it perfo

Matt Webb 32 Dec 30, 2022
11ty starter: uses md and notion as data sources

eleventy_notion_starter 11ty starter: uses md and notion as data sources. Based on https://github.com/siakaramalegos/11ty-sia-blog. Used to power http

Thiago Margarida 18 Oct 26, 2022
With this script you can bypass both root detection and ssl pinning for your android app.

frida_rootansslbypas ██████╗ ██████╗ ██████╗ ████████╗ █████╗ ███╗ ██╗██████╗ ███████╗███████╗██╗ ██████╗ ██╗ ██╗██████╗ █████╗

themalwarenews 14 Dec 24, 2022
A CLI to write journal for you and save it to a Notion database!

Journal CLI NPM Link A CLI to write journal for you and save it to a Notion database! Demo Installation Run npm i -g journal-notion-cli to install the

Amit Wani 5 Oct 7, 2022
Send messages to this bot and almacenate it on selected Notion's Database

Telegram to Notion Bot What can do this bot? With this bot you can authorize that it receive the text that you send and store it on one selected datab

Francisco Pessano 24 Dec 11, 2022
Tool for publishing posts to mitchinson.dev from a Notion database

Notion Publish Tool - publish.mitchinson.dev A publishing API for mirroring Notion posts to mitchinson.dev Includes: Asset uploading to Cloudinary CDN

Ben Mitchinson 6 Dec 23, 2022
A CloudFlare Worker / script / bot to sync Notion pages publicly as GitHub Discussions.

notion-github-sync This bot syncs public Notion pages as GitHub Discussions/Issues. It's done periodically, based on the pages shared with the Notion

The Guild 20 Dec 22, 2022
A landing page, as well as a results page, that utliize both Yelp API and Google Maps API.

Economic Eats Group Project #1 Maintained By: Austin Donovan John Hysong John Guzzetta Jahnathan Exantus Description This project contains a landing p

John Guzzetta IV 7 Aug 4, 2022
This is a simple script to upload Multiple files into google drive using google drive API and Nodejs.

Welcome to gDrive Multiple File Upload ?? This is a simple script to upload Multiple files into google drive using google drive API and Nodejs Install

Jayamal Sanuka Hettiarachchi 1 Dec 29, 2021
A high-resolution local database that uses precise algorithms to easily record data in local files within a project with persistent JSON and YAML support designed to be easy to set up and use

About A high-resolution local database that uses precise algorithms to easily record data in local files within a project with persistent JSON and YML

Shuruhatik 5 Dec 28, 2022
Google-Drive-Directory-Index | Combining the power of Cloudflare Workers and Google Drive API will allow you to index your Google Drive files on the browser.

?? Google-Drive-Directory-Index Combining the power of Cloudflare Workers and Google Drive will allow you to index your Google Drive files on the brow

Aicirou 127 Jan 2, 2023
A sample Node.js application that uses the database-js package.

database-js-starter A sample Node.js Express API built using the PlanetScale serverless driver for JavaScript. It contains sample API endpoints that c

PlanetScale 7 Dec 19, 2022
Interplanetary Database: A Database built on top of IPFS and made immutable using Ethereum blockchain.

IPDB IPDB (Interplanetary Database) is a key/value store database built on top of IPFS (Interplanetary File System). Project is intended to be an MVP

turinglabs 8 Oct 6, 2022
Visualize, modify, and build your database with dbSpy! An open-source data modeling tool to facilitate relational database development.

Visualize, modify, and build your database with dbSpy! dbSpy is an open-source data modeling tool to facilitate relational database development. Key F

OSLabs 115 Dec 22, 2022
DoMe is a ToDo App. you can add, delete and reorder elements of the todo list using drag and drop. You can also toggle between dark&light mode

DO ME Todo App Live Preview : DO ME Built With : - ReactJS - TailwindCSS Make sure you have: - Git - Nodejs version 14 or higher (we recommend using

Medjahdi Islem 5 Nov 18, 2022
Seamlessly connect your web server to Rebrandly so that you can re-use your domain name for both your app and your short links

rebrandly-express Seamlessly connect your web server to Rebrandly so that you can re-use your domain name for both your app and your short links Rebra

null 3 Dec 13, 2022
A monorepo containing both the $CODE token contract & the claim web app.

DeveloperDAO $CODE contract & claim site A monorepo containing both the $CODE token contract & the claim web app. Contents Related Development Prerequ

Developer DAO 27 Jul 12, 2022