diff --git a/notion/client.py b/notion/client.py index 9060f46..ad9e884 100644 --- a/notion/client.py +++ b/notion/client.py @@ -9,6 +9,7 @@ from requests.adapters import HTTPAdapter from requests.packages.urllib3.util.retry import Retry from getpass import getpass +from time import sleep from .block import Block, BLOCK_TYPES from .collection import ( @@ -373,7 +374,46 @@ def create_record(self, table, parent, **kwargs): ) return record_id + + def get_task_status(self, task_id): + """ + Get a status of a single task + """ + data = self.post( + "getTasks", + { + "taskIds": [task_id] + } + ).json() + + results = data.get("results") + if results is None: + return None + + if not results: + # Notion does not know about such a task + print("Invalid task ID.") + return None + if len(results) == 1: + state = results[0].get("state") + return state + + return None + + def wait_for_task(self, task_id, interval=1, tries=10): + """ + Wait for a task by looping 'tries' times ever 'interval' seconds. + The 'interval' parameter can be used to specify milliseconds using double (e.g 0.75). + """ + for i in range(tries): + state = self.get_task_status(task_id) + if state in ["not_started", "in_progress"]: + sleep(interval) + elif state == "success": + return state + + print("Task takes more time than expected. Specify 'interval' or 'tries' to wait more.") class Transaction(object): diff --git a/notion/collection.py b/notion/collection.py index 37e8421..9690437 100644 --- a/notion/collection.py +++ b/notion/collection.py @@ -186,14 +186,40 @@ def get_schema_property(self, identifier): return prop return None - def add_row(self, update_views=True, **kwargs): + def add_row(self, update_views=True, source_block=None, **kwargs): """ Create a new empty CollectionRowBlock under this collection, and return the instance. + Specify 'source_block' to create a row from a template block. """ row_id = self._client.create_record("block", self, type="page") row = CollectionRowBlock(self._client, row_id) + # User wants to create a row from a template + if source_block: + # The source block can be either an ID or a URL + source_block = self._client.get_block(source_block) + # Start a duplication task + data = self._client.post( + "enqueueTask", + { + "task": { + "eventName": "duplicateBlock", + "request": { + "sourceBlockId": source_block.id, + "targetBlockId": row_id, + "appendContentOnly": True + } + } + }, + ).json() + + task_id = data.get("taskId") + + if task_id: + # Wait until the duplication task finishes + self._client.wait_for_task(task_id) + with self._client.as_atomic_transaction(): for key, val in kwargs.items(): setattr(row, key, val)