From befc50f21e34c4c4847ec7705d34188853cc6cb8 Mon Sep 17 00:00:00 2001 From: Kris Date: Sun, 5 Nov 2023 22:24:01 +0000 Subject: [PATCH 1/6] figure out how to update --- sync/google_to_notion_task_sync.py | 50 ++++++++++++++++++++++++++++-- sync/main.py | 44 ++++++++++++++++++++++++++ 2 files changed, 91 insertions(+), 3 deletions(-) create mode 100644 sync/main.py diff --git a/sync/google_to_notion_task_sync.py b/sync/google_to_notion_task_sync.py index ef54676..ddb6b14 100644 --- a/sync/google_to_notion_task_sync.py +++ b/sync/google_to_notion_task_sync.py @@ -1,10 +1,54 @@ """Script that handles the sync from Google Tasks to Notion""" +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 google.auth.transport.requests import Request +from google.oauth2.credentials import Credentials +from google_auth_oauthlib.flow import InstalledAppFlow +from googleapiclient.discovery import build +from googleapiclient.errors import HttpError +import redis +from notion_to_google_task_sync import authenticate_and_print # 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 +# TODO: Currently you have a Many-to-one relationship, you might want to have a to One-to-one relationship +# DONE If a task is ticked on Google Calendar, it should be ticket on Notion as well, etc. +# DONE If a task is changed (text edited) in GC it should be changed in Notion as well +# TODO If a task is deleted on GC, if should be deleted in Notion as well + + +def insert_google_task_into_notion(service, 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"] + ] + + + +if __name__ == "__main__": + load_dotenv() + NOTION_ID = os.getenv("NOTION_KEY") + + client = Client(auth=NOTION_ID) + service = authenticate_and_print() + + # this is the functionality that needs to be generalised in a function, + # this will be used for changed text and tick box changes + block = client.blocks.retrieve("0f3d06aa-4a00-4ce8-81cd-02e9ea24efb1") + print(block) + block["to_do"]["checked"] = False + block["to_do"]["rich_text"][0]["text"]["content"] = "Hello World" + + client.blocks.update("0f3d06aa-4a00-4ce8-81cd-02e9ea24efb1", **block) + + print(block) + # insert_google_task_into_notion(service, task_list_id) \ No newline at end of file diff --git a/sync/main.py b/sync/main.py new file mode 100644 index 0000000..7d68888 --- /dev/null +++ b/sync/main.py @@ -0,0 +1,44 @@ +# import all necessary functions/classes from both files for a single run script + + +# 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) From d1f0d1de83ce31ff620295f43b6b5c03bb276af2 Mon Sep 17 00:00:00 2001 From: Kris Date: Sat, 25 Nov 2023 23:48:22 +0000 Subject: [PATCH 2/6] one-to-one mapping enabled --- sync/google_to_notion_task_sync.py | 4 +++ sync/notion_to_google_task_sync.py | 44 ++++++++++++++++-------------- 2 files changed, 27 insertions(+), 21 deletions(-) diff --git a/sync/google_to_notion_task_sync.py b/sync/google_to_notion_task_sync.py index ddb6b14..a909650 100644 --- a/sync/google_to_notion_task_sync.py +++ b/sync/google_to_notion_task_sync.py @@ -18,8 +18,12 @@ # Extra features: # (???) If a task is added to GC, it should be added to Notion as well (???) Where? # TODO: Currently you have a Many-to-one relationship, you might want to have a to One-to-one relationship +# This is what we want to work on now, we cant establish a true two way connection until we have one to one mapping + +# TODO: Also, update the redis db to have the reverse mapping, map from G id to N id + # DONE If a task is ticked on Google Calendar, it should be ticket on Notion as well, etc. # DONE If a task is changed (text edited) in GC it should be changed in Notion as well # TODO If a task is deleted on GC, if should be deleted in Notion as well diff --git a/sync/notion_to_google_task_sync.py b/sync/notion_to_google_task_sync.py index a1a295a..bb859fb 100644 --- a/sync/notion_to_google_task_sync.py +++ b/sync/notion_to_google_task_sync.py @@ -15,7 +15,7 @@ from googleapiclient.errors import HttpError import redis -logging.basicConfig(level=logging.DEBUG) +# logging.basicConfig(level=logging.DEBUG) # ----------------- # SETUP @@ -133,15 +133,15 @@ 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() + service.tasklists().insert(body={"title": title}).execute() ) return new_task_list["id"] @@ -193,7 +193,7 @@ def remove_deleted_tasks_ids_from_redis(service, notion_tasks, task_list_id): if __name__ == "__main__": load_dotenv() - NOTION_ID = os.getenv("NOTION_KEY") #NOTION_KEY + NOTION_ID = os.getenv("NOTION_KEY") # NOTION_KEY if NOTION_ID is None: raise KeyError("Missing NOTION ID environment variable") @@ -206,30 +206,32 @@ def remove_deleted_tasks_ids_from_redis(service, notion_tasks, task_list_id): page_ids = get_all_pages(client) # Get every block from each page id - all_blocks = [] + total_blocks = [] + for page_id in page_ids: - all_blocks.extend(get_all_blocks(client, page_id)) + total_blocks.extend(get_all_blocks(client, page_id)) # Get all Notion todos - notion_tasks = get_todo(client, all_blocks) + total_notion_tasks = get_todo(client, total_blocks) + + for page_id in page_ids: + # import ipdb;ipdb.set_trace() + all_blocks = [] + + all_blocks.extend(get_all_blocks(client, page_id)) + notion_tasks = get_todo(client, all_blocks) + - TASK_LIST_ID = create_notion_tasklist(service) + 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) + # 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) + remove_deleted_tasks_ids_from_redis(service, total_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) + update_google_tasks(service, notion_tasks, TASK_LIST_ID) From 6646aca3d3f5229e509d7c5d81cff6d50bb272ed Mon Sep 17 00:00:00 2001 From: Kris Date: Sun, 26 Nov 2023 18:29:13 +0000 Subject: [PATCH 3/6] update N from GT --- sync/google_to_notion_task_sync.py | 68 +++++++++++++++++------------- sync/notion_to_google_task_sync.py | 11 +++-- 2 files changed, 46 insertions(+), 33 deletions(-) diff --git a/sync/google_to_notion_task_sync.py b/sync/google_to_notion_task_sync.py index a909650..7951e5f 100644 --- a/sync/google_to_notion_task_sync.py +++ b/sync/google_to_notion_task_sync.py @@ -1,41 +1,53 @@ """Script that handles the sync from Google Tasks to Notion""" 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 google.auth.transport.requests import Request -from google.oauth2.credentials import Credentials -from google_auth_oauthlib.flow import InstalledAppFlow -from googleapiclient.discovery import build -from googleapiclient.errors import HttpError -import redis -from notion_to_google_task_sync import authenticate_and_print - -# Extra features: -# (???) If a task is added to GC, it should be added to Notion as well (???) Where? -# TODO: Currently you have a Many-to-one relationship, you might want to have a to One-to-one relationship -# This is what we want to work on now, we cant establish a true two way connection until we have one to one mapping +from notion_to_google_task_sync import authenticate_and_print +from notion_to_google_task_sync import r_reverse -# TODO: Also, update the redis db to have the reverse mapping, map from G id to N id +# DONE: Also, update the redis db to have the reverse mapping, map from G id to N id # DONE If a task is ticked on Google Calendar, it should be ticket on Notion as well, etc. # DONE If a task is changed (text edited) in GC it should be changed in Notion as well -# TODO If a task is deleted on GC, if should be deleted in Notion as well +# TODO If a task is added in GC, add it to Notion, corresponding page AND redis +# TODO If a task is deleted on GC, if should be deleted in Notion as well AND in the database + + +# def insert_google_task_into_notion(service, 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"] +# ] + + +def update_notion_tasks(service, client, task_list_id): + """Function that Updates tasks. Closes tasks marked as completed from Notion to Google Takss""" -def insert_google_task_into_notion(service, 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 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) + if __name__ == "__main__": @@ -47,12 +59,8 @@ def insert_google_task_into_notion(service, task_list_id): # this is the functionality that needs to be generalised in a function, # this will be used for changed text and tick box changes - block = client.blocks.retrieve("0f3d06aa-4a00-4ce8-81cd-02e9ea24efb1") - print(block) - block["to_do"]["checked"] = False - block["to_do"]["rich_text"][0]["text"]["content"] = "Hello World" - - client.blocks.update("0f3d06aa-4a00-4ce8-81cd-02e9ea24efb1", **block) + # insert_google_task_into_notion(service, task_list_id) + # import ipdb;ipdb.set_trace() + update_notion_tasks(service, client, task_list_id="eEctUkkwdGctZ3Q1d3RoQg") - print(block) - # insert_google_task_into_notion(service, task_list_id) \ No newline at end of file + tasklists_id = ["eEctUkkwdGctZ3Q1d3RoQg", "TXN4Y01pN2FOTk9kTnpUbw", "aXBIaHhfNVMzeGo5VWVncg"] \ No newline at end of file diff --git a/sync/notion_to_google_task_sync.py b/sync/notion_to_google_task_sync.py index bb859fb..acd49fb 100644 --- a/sync/notion_to_google_task_sync.py +++ b/sync/notion_to_google_task_sync.py @@ -22,7 +22,9 @@ 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 @@ -170,6 +172,8 @@ 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']}" ) @@ -187,13 +191,14 @@ 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) - + r_reverse.delete(google_task_id) if __name__ == "__main__": load_dotenv() - NOTION_ID = os.getenv("NOTION_KEY") # NOTION_KEY + NOTION_ID = os.getenv("NOTION_KEY") if NOTION_ID is None: raise KeyError("Missing NOTION ID environment variable") From ce76f0e13a262be52f4c26ffcf8b592ea2fe1dc9 Mon Sep 17 00:00:00 2001 From: Kris Date: Sun, 3 Dec 2023 00:39:55 +0000 Subject: [PATCH 4/6] insert tasks from GT to N --- sync/google_to_notion_task_sync.py | 94 ++++++++++++++++++++++++------ 1 file changed, 76 insertions(+), 18 deletions(-) diff --git a/sync/google_to_notion_task_sync.py b/sync/google_to_notion_task_sync.py index 7951e5f..6438344 100644 --- a/sync/google_to_notion_task_sync.py +++ b/sync/google_to_notion_task_sync.py @@ -3,26 +3,79 @@ from notion_client import Client from dotenv import load_dotenv import os.path - +from typing import List from notion_to_google_task_sync import authenticate_and_print -from notion_to_google_task_sync import r_reverse +from notion_to_google_task_sync import r_reverse, r + + +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 # DONE: Also, update the redis db to have the reverse mapping, map from G id to N id # DONE If a task is ticked on Google Calendar, it should be ticket on Notion as well, etc. # DONE If a task is changed (text edited) in GC it should be changed in Notion as well -# TODO If a task is added in GC, add it to Notion, corresponding page AND redis +# DONE If a task is added in GC, add it to Notion, corresponding page AND redis # TODO If a task is deleted on GC, if should be deleted in Notion as well AND in the database +# TODO Add logic to prevent user from adding a notion page with a title that already exist in GT + +# TODO ?? What if we create a new GT page? Should we create a new Notion page? +# Like we currently do the other way around? + + +def insert_google_task_into_notion(service, client, 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"] + ] + + # import ipdb;ipdb.set_trace() + + google_tasklist_title = ( + service.tasklists().get(tasklist=task_list_id).execute()["title"] + ) -# def insert_google_task_into_notion(service, 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"] -# ] + pages_data = get_pages_data(client) + # get the notion page id of the page where we want to insert the new task + notion_page_id = pages_data[google_tasklist_title] + + 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"] + ) # correct one notion_task["results"][0]["id"] + r_reverse.set(google_task["id"], notion_task["results"][0]["id"]) def update_notion_tasks(service, client, task_list_id): @@ -30,7 +83,9 @@ def update_notion_tasks(service, client, task_list_id): 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 task in service.tasks() + .list(tasklist=task_list_id, showHidden=True) + .execute()["items"] ] for google_task in current_google_tasks: @@ -42,25 +97,28 @@ def update_notion_tasks(service, client, task_list_id): 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) - if __name__ == "__main__": load_dotenv() - NOTION_ID = os.getenv("NOTION_KEY") + NOTION_ID = os.getenv("NOTION_KEY") client = Client(auth=NOTION_ID) service = authenticate_and_print() - # this is the functionality that needs to be generalised in a function, - # this will be used for changed text and tick box changes - # insert_google_task_into_notion(service, task_list_id) - # import ipdb;ipdb.set_trace() + tasklists_id = [ + "eEctUkkwdGctZ3Q1d3RoQg", + "TXN4Y01pN2FOTk9kTnpUbw", + "aXBIaHhfNVMzeGo5VWVncg", + ] + update_notion_tasks(service, client, task_list_id="eEctUkkwdGctZ3Q1d3RoQg") - tasklists_id = ["eEctUkkwdGctZ3Q1d3RoQg", "TXN4Y01pN2FOTk9kTnpUbw", "aXBIaHhfNVMzeGo5VWVncg"] \ No newline at end of file + insert_google_task_into_notion( + service, client, task_list_id="eEctUkkwdGctZ3Q1d3RoQg" + ) From a4a6cd8ad1493743262d199b0c9ba75536311c44 Mon Sep 17 00:00:00 2001 From: Kris Date: Sat, 9 Dec 2023 18:34:18 +0000 Subject: [PATCH 5/6] finish delete action from GT to NT --- sync/google_to_notion_task_sync.py | 63 +++++++++++++++++++----------- sync/notion_to_google_task_sync.py | 5 --- 2 files changed, 41 insertions(+), 27 deletions(-) diff --git a/sync/google_to_notion_task_sync.py b/sync/google_to_notion_task_sync.py index 6438344..0d5d2bd 100644 --- a/sync/google_to_notion_task_sync.py +++ b/sync/google_to_notion_task_sync.py @@ -24,12 +24,7 @@ def get_pages_data(client: Client) -> List[str]: # DONE If a task is ticked on Google Calendar, it should be ticket on Notion as well, etc. # DONE If a task is changed (text edited) in GC it should be changed in Notion as well # DONE If a task is added in GC, add it to Notion, corresponding page AND redis -# TODO If a task is deleted on GC, if should be deleted in Notion as well AND in the database - -# TODO Add logic to prevent user from adding a notion page with a title that already exist in GT - -# TODO ?? What if we create a new GT page? Should we create a new Notion page? -# Like we currently do the other way around? +# DONE If a task is deleted on GC, if should be deleted in Notion as well AND in the database def insert_google_task_into_notion(service, client, task_list_id): @@ -40,18 +35,15 @@ def insert_google_task_into_notion(service, client, task_list_id): for task in service.tasks().list(tasklist=task_list_id).execute()["items"] ] - # import ipdb;ipdb.set_trace() - + # get the notion page id of the page where we want to insert the new task google_tasklist_title = ( service.tasklists().get(tasklist=task_list_id).execute()["title"] ) - pages_data = get_pages_data(client) - - # get the notion page id of the page where we want to insert the new task notion_page_id = pages_data[google_tasklist_title] for google_task in current_google_tasks[::-1]: + # if we reach an id that if r_reverse.get(google_task["id"]) is None: if google_task["status"] == "needsAction": @@ -72,12 +64,35 @@ def insert_google_task_into_notion(service, client, task_list_id): ) # this should be done in another function. Use it for demo for now - r.set( - notion_task["results"][0]["id"], google_task["id"] - ) # correct one notion_task["results"][0]["id"] + 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_ids): + """Delete NT that has been removed from GT""" + + current_google_task_ids = [] + + for tasklist_id in task_list_ids: # get all tasks from each Google tasklist + + current_google_task_ids.extend( + [ + task["id"] + for task in service.tasks() + .list(tasklist=tasklist_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""" @@ -111,14 +126,18 @@ def update_notion_tasks(service, client, task_list_id): client = Client(auth=NOTION_ID) service = authenticate_and_print() - tasklists_id = [ - "eEctUkkwdGctZ3Q1d3RoQg", - "TXN4Y01pN2FOTk9kTnpUbw", - "aXBIaHhfNVMzeGo5VWVncg", - ] - - update_notion_tasks(service, client, task_list_id="eEctUkkwdGctZ3Q1d3RoQg") + update_notion_tasks(service, client, task_list_id="dWtPeGlHSkQycFJzbS1CRA") insert_google_task_into_notion( - service, client, task_list_id="eEctUkkwdGctZ3Q1d3RoQg" + service, client, task_list_id="dWtPeGlHSkQycFJzbS1CRA" ) + + # TODO: Last one, you need to be able to get all tasklist ids from GT, avoiding the Defaul list + # TODO Add logic to prevent user from adding a notion page with a title that already exist in GT + tasklist_ids = [ + "dWtPeGlHSkQycFJzbS1CRA", + "d3g2elhWNkc5UzdLNmo5Yw", + "OTBJZnR3ZllvUUNCa3NJUA", + ] + + remove_deleted_google_tasks(service, client, task_list_ids=tasklist_ids) diff --git a/sync/notion_to_google_task_sync.py b/sync/notion_to_google_task_sync.py index acd49fb..733d557 100644 --- a/sync/notion_to_google_task_sync.py +++ b/sync/notion_to_google_task_sync.py @@ -120,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: From 70a04fef2232ba39725ec9f6411f4f62fab47d4d Mon Sep 17 00:00:00 2001 From: Kris Date: Sat, 16 Dec 2023 17:02:44 +0000 Subject: [PATCH 6/6] update main --- main.py | 66 ++++++++++++++++++++++++++++++ sync/google_to_notion_task_sync.py | 65 ++++------------------------- sync/main.py | 44 -------------------- sync/notion_to_google_task_sync.py | 54 ++---------------------- 4 files changed, 79 insertions(+), 150 deletions(-) create mode 100644 main.py delete mode 100644 sync/main.py diff --git a/main.py b/main.py new file mode 100644 index 0000000..b4cc45b --- /dev/null +++ b/main.py @@ -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) + diff --git a/sync/google_to_notion_task_sync.py b/sync/google_to_notion_task_sync.py index 0d5d2bd..1ca7738 100644 --- a/sync/google_to_notion_task_sync.py +++ b/sync/google_to_notion_task_sync.py @@ -1,11 +1,7 @@ """Script that handles the sync from Google Tasks to Notion""" -import os from notion_client import Client -from dotenv import load_dotenv -import os.path from typing import List -from notion_to_google_task_sync import authenticate_and_print -from notion_to_google_task_sync import r_reverse, r +from sync.notion_to_google_task_sync import r_reverse, r def get_pages_data(client: Client) -> List[str]: @@ -20,14 +16,7 @@ def get_pages_data(client: Client) -> List[str]: return pages_data -# DONE: Also, update the redis db to have the reverse mapping, map from G id to N id -# DONE If a task is ticked on Google Calendar, it should be ticket on Notion as well, etc. -# DONE If a task is changed (text edited) in GC it should be changed in Notion as well -# DONE If a task is added in GC, add it to Notion, corresponding page AND redis -# DONE If a task is deleted on GC, if should be deleted in Notion as well AND in the database - - -def insert_google_task_into_notion(service, client, task_list_id): +def insert_google_task_into_notion(service, client, notion_page_id, task_list_id): """Insert google tasks into notion""" current_google_tasks = [ @@ -35,15 +24,7 @@ def insert_google_task_into_notion(service, client, task_list_id): for task in service.tasks().list(tasklist=task_list_id).execute()["items"] ] - # get the notion page id of the page where we want to insert the new task - google_tasklist_title = ( - service.tasklists().get(tasklist=task_list_id).execute()["title"] - ) - pages_data = get_pages_data(client) - notion_page_id = pages_data[google_tasklist_title] - for google_task in current_google_tasks[::-1]: - # if we reach an id that if r_reverse.get(google_task["id"]) is None: if google_task["status"] == "needsAction": @@ -68,21 +49,17 @@ def insert_google_task_into_notion(service, client, task_list_id): r_reverse.set(google_task["id"], notion_task["results"][0]["id"]) -def remove_deleted_google_tasks(service, client, task_list_ids): +def remove_deleted_google_tasks(service, client, task_list_id): """Delete NT that has been removed from GT""" current_google_task_ids = [] - for tasklist_id in task_list_ids: # get all tasks from each Google tasklist - - current_google_task_ids.extend( - [ - task["id"] - for task in service.tasks() - .list(tasklist=tasklist_id, showHidden=True) - .execute()["items"] - ] - ) + 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: @@ -117,27 +94,3 @@ def update_notion_tasks(service, client, task_list_id): block["to_do"]["rich_text"][0]["plain_text"] = google_task["title"] client.blocks.update(r_reverse.get(google_task["id"]), **block) - - -if __name__ == "__main__": - load_dotenv() - NOTION_ID = os.getenv("NOTION_KEY") - - client = Client(auth=NOTION_ID) - service = authenticate_and_print() - - update_notion_tasks(service, client, task_list_id="dWtPeGlHSkQycFJzbS1CRA") - - insert_google_task_into_notion( - service, client, task_list_id="dWtPeGlHSkQycFJzbS1CRA" - ) - - # TODO: Last one, you need to be able to get all tasklist ids from GT, avoiding the Defaul list - # TODO Add logic to prevent user from adding a notion page with a title that already exist in GT - tasklist_ids = [ - "dWtPeGlHSkQycFJzbS1CRA", - "d3g2elhWNkc5UzdLNmo5Yw", - "OTBJZnR3ZllvUUNCa3NJUA", - ] - - remove_deleted_google_tasks(service, client, task_list_ids=tasklist_ids) diff --git a/sync/main.py b/sync/main.py deleted file mode 100644 index 7d68888..0000000 --- a/sync/main.py +++ /dev/null @@ -1,44 +0,0 @@ -# import all necessary functions/classes from both files for a single run script - - -# 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) diff --git a/sync/notion_to_google_task_sync.py b/sync/notion_to_google_task_sync.py index 733d557..65e6fdc 100644 --- a/sync/notion_to_google_task_sync.py +++ b/sync/notion_to_google_task_sync.py @@ -137,9 +137,7 @@ def create_notion_tasklist(service, title) -> str: if task_list["title"] == title: return task_list["id"] - new_task_list = ( - service.tasklists().insert(body={"title": title}).execute() - ) + new_task_list = service.tasklists().insert(body={"title": title}).execute() return new_task_list["id"] @@ -167,7 +165,9 @@ 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 + 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']}" @@ -189,49 +189,3 @@ def remove_deleted_tasks_ids_from_redis(service, notion_tasks, task_list_id): google_task_id = r.get(notion_id_in_db) r.delete(notion_id_in_db) r_reverse.delete(google_task_id) - -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: - # import ipdb;ipdb.set_trace() - 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) - -