Skip to content

Commit

Permalink
Merge pull request #10 from kris524/google_to_notion_sync
Browse files Browse the repository at this point in the history
Reverse-Sync from G to N
  • Loading branch information
kris524 authored Dec 16, 2023
2 parents aa53dd1 + 70a04fe commit cf1d5fe
Show file tree
Hide file tree
Showing 3 changed files with 170 additions and 62 deletions.
66 changes: 66 additions & 0 deletions main.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import os
from notion_client import Client
from pprint import pprint
from dotenv import load_dotenv
from typing import List, Dict
import os.path
import logging

from sync.notion_to_google_task_sync import (
authenticate_and_print,
get_all_pages,
get_all_blocks,
get_todo,
create_notion_tasklist,
insert_notion_tasks_in_google_tasks,
add_id_mapping_to_redis,
update_google_tasks,
remove_deleted_tasks_ids_from_redis,
)

from sync.google_to_notion_task_sync import (
update_notion_tasks,
remove_deleted_google_tasks,
insert_google_task_into_notion,
)

if __name__ == "__main__":

load_dotenv()
NOTION_ID = os.getenv("NOTION_KEY")
if NOTION_ID is None:
raise KeyError("Missing NOTION ID environment variable")

service = authenticate_and_print()

# Create Client
client = Client(auth=NOTION_ID)

# Get all page ids
page_ids = get_all_pages(client)

# Get every block from each page id
total_blocks = []

for page_id in page_ids:
total_blocks.extend(get_all_blocks(client, page_id))

# Get all Notion todos
total_notion_tasks = get_todo(client, total_blocks)


for page_id in page_ids:
all_blocks = []

all_blocks.extend(get_all_blocks(client, page_id))
notion_tasks = get_todo(client, all_blocks)

title = client.blocks.retrieve(page_id)["child_page"]["title"]
TASK_LIST_ID = create_notion_tasklist(service, title)

# Insert tasks from Notion to Google
insert_notion_tasks_in_google_tasks(service, notion_tasks, TASK_LIST_ID)
add_id_mapping_to_redis(service, notion_tasks, TASK_LIST_ID)
remove_deleted_tasks_ids_from_redis(service, total_notion_tasks, TASK_LIST_ID)
update_google_tasks(service, notion_tasks, TASK_LIST_ID)

96 changes: 91 additions & 5 deletions sync/google_to_notion_task_sync.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,96 @@
"""Script that handles the sync from Google Tasks to Notion"""
from notion_client import Client
from typing import List
from sync.notion_to_google_task_sync import r_reverse, r


# Extra features:
# (???) If a task is added to GC, it should be added to Notion as well (???) Where?
# If a task is ticked on Google Calendar, it should be ticket on Notion as well, etc.
# If a task is changed (text edited) in GC it should be changed in Notion as well
# If a task is deleted on GC, if should be deleted in Notion as well
def get_pages_data(client: Client) -> List[str]:
"""Get all pages that have enabled the integration"""
# import ipdb;ipdb.set_trace()
pages_data = {}
for page in client.search()["results"]:

title = page["properties"]["title"]["title"][0]["plain_text"]
pages_data[title] = page["id"]

return pages_data


def insert_google_task_into_notion(service, client, notion_page_id, task_list_id):
"""Insert google tasks into notion"""

current_google_tasks = [
{"title": task["title"], "id": task["id"], "status": task["status"]}
for task in service.tasks().list(tasklist=task_list_id).execute()["items"]
]

for google_task in current_google_tasks[::-1]:
if r_reverse.get(google_task["id"]) is None:

if google_task["status"] == "needsAction":
checked = False
else:
checked = True

notion_task = client.blocks.children.append(
notion_page_id,
children=[
{
"to_do": {
"rich_text": [{"text": {"content": google_task["title"]}}],
"checked": checked,
}
}
],
)

# this should be done in another function. Use it for demo for now
r.set(notion_task["results"][0]["id"], google_task["id"])
r_reverse.set(google_task["id"], notion_task["results"][0]["id"])


def remove_deleted_google_tasks(service, client, task_list_id):
"""Delete NT that has been removed from GT"""

current_google_task_ids = []

current_google_task_ids = [
task["id"]
for task in service.tasks()
.list(tasklist=task_list_id, showHidden=True)
.execute()["items"]
]

for google_task_id in r_reverse.keys():
if google_task_id not in current_google_task_ids:

notion_id_in_db = r_reverse.get(google_task_id)
client.blocks.delete(notion_id_in_db)
r.delete(notion_id_in_db)
r_reverse.delete(google_task_id)


def update_notion_tasks(service, client, task_list_id):
"""Function that Updates tasks. Closes tasks marked as completed from Notion to Google Takss"""

current_google_tasks = [
{"title": task["title"], "id": task["id"], "status": task["status"]}
for task in service.tasks()
.list(tasklist=task_list_id, showHidden=True)
.execute()["items"]
]

for google_task in current_google_tasks:

if r_reverse.get(google_task["id"]) is not None:
block = client.blocks.retrieve(r_reverse.get(google_task["id"]))

if google_task["status"] == "needsAction":
block["to_do"]["checked"] = False
else:
block["to_do"]["checked"] = True

block["to_do"]["rich_text"][0]["text"]["content"] = google_task["title"]
block["to_do"]["rich_text"][0]["plain_text"] = google_task["title"]

client.blocks.update(r_reverse.get(google_task["id"]), **block)
70 changes: 13 additions & 57 deletions sync/notion_to_google_task_sync.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,16 @@
from googleapiclient.errors import HttpError
import redis

logging.basicConfig(level=logging.DEBUG)
# logging.basicConfig(level=logging.DEBUG)

# -----------------
# SETUP

SCOPES = ["https://www.googleapis.com/auth/tasks"]

r = redis.Redis(host="localhost", port=6379, decode_responses=True)
r = redis.Redis(host="localhost", port=6379, decode_responses=True, db=0)

r_reverse = redis.Redis(host="localhost", port=6379, decode_responses=True, db=1)

# -----------------
# NOTION FUNCTIONS
Expand Down Expand Up @@ -118,11 +120,6 @@ def insert_notion_tasks_in_google_tasks(service, notion_tasks, task_list_id):
def update_google_tasks(service, notion_tasks, task_list_id):
"""Function that Updates tasks. Closes tasks marked as completed from Notion to Google Takss"""

current_google_tasks = [
{"title": task["title"], "id": task["id"], "status": task["status"]}
for task in service.tasks().list(tasklist=task_list_id).execute()["items"]
]

for notion_task in notion_tasks:

if r.get(notion_task["id"]) is not None:
Expand All @@ -133,16 +130,14 @@ def update_google_tasks(service, notion_tasks, task_list_id):
).execute()


def create_notion_tasklist(service) -> str:
def create_notion_tasklist(service, title) -> str:
"""Create a dedicated TaskList in Google Tasks if it does not exist"""

for task_list in service.tasklists().list().execute()["items"]:
if task_list["title"] == "Tasks from Notion":
if task_list["title"] == title:
return task_list["id"]

new_task_list = (
service.tasklists().insert(body={"title": "Tasks from Notion"}).execute()
)
new_task_list = service.tasklists().insert(body={"title": title}).execute()
return new_task_list["id"]


Expand Down Expand Up @@ -170,6 +165,10 @@ def add_id_mapping_to_redis(service, notion_tasks, task_list_id):
and notion_task["status"] == google_task["status"]
):
r.set(notion_task["id"], google_task["id"])
r_reverse.set(
google_task["id"], notion_task["id"]
) # store reverse mapping in db1

logging.info(
f"Successfully added k: {notion_task['id']} v: {google_task['id']}"
)
Expand All @@ -187,49 +186,6 @@ def remove_deleted_tasks_ids_from_redis(service, notion_tasks, task_list_id):
service.tasks().delete(
tasklist=task_list_id, task=r.get(notion_id_in_db)
).execute()
google_task_id = r.get(notion_id_in_db)
r.delete(notion_id_in_db)


if __name__ == "__main__":

load_dotenv()
NOTION_ID = os.getenv("NOTION_KEY") #NOTION_KEY
if NOTION_ID is None:
raise KeyError("Missing NOTION ID environment variable")

service = authenticate_and_print()

# Create Client
client = Client(auth=NOTION_ID)

# Get all page ids
page_ids = get_all_pages(client)

# Get every block from each page id
all_blocks = []
for page_id in page_ids:
all_blocks.extend(get_all_blocks(client, page_id))

# Get all Notion todos
notion_tasks = get_todo(client, all_blocks)

TASK_LIST_ID = create_notion_tasklist(service)

# Insert tasks from Notion to Google
insert_notion_tasks_in_google_tasks(service, notion_tasks, TASK_LIST_ID)

# TODO replace .keys() with something more efficient later
# If redis is empty, or new todo has been added, update the database
if not r.keys() or len(r.keys()) < len(notion_tasks): # add a
logging.info("Adding new data to Redis")
add_id_mapping_to_redis(service, notion_tasks, TASK_LIST_ID)

# If redis has more keys than current notion_tasks, delete the Google task and that key
if len(r.keys()) > len(notion_tasks):
logging.info("Deleting tasks")
remove_deleted_tasks_ids_from_redis(service, notion_tasks, TASK_LIST_ID)

# Update the state of tasks, whenever needed (checked, changed name, etc.)
update_google_tasks(service, notion_tasks, TASK_LIST_ID)


r_reverse.delete(google_task_id)

0 comments on commit cf1d5fe

Please sign in to comment.