Last active
January 31, 2024 00:46
-
-
Save error9900/b3e18c803a39bb4a9147be37faf595f7 to your computer and use it in GitHub Desktop.
Change one Label to another Label on all tasks with the first Label...
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
""" | |
This will find all Tasks with a specific Label, remove that Label, and add another specified Label. | |
Make sure you add your API token to `data/token.txt`! | |
You'll need the Python SDK for this to work: | |
https://developer.todoist.com/rest/v2/#python-sdk | |
""" | |
import uuid | |
import requests | |
import todoist_api_python.api | |
SESSION = requests.Session() | |
def load_token(): | |
with open("data/token.txt", "r", encoding="utf-8") as file: | |
line = file.readline() | |
token = line.strip() | |
return token | |
todoist_api = todoist_api_python.api.TodoistAPI(load_token()) | |
def check_response(response): | |
if not response.ok: | |
raise ValueError(f"Error: {response.content}") | |
def sync_post(body): | |
response = SESSION.post( | |
"https://api.todoist.com/sync/v9/sync", | |
headers={"Authorization": f"Bearer {load_token()}"}, | |
json=body, | |
timeout=60, | |
) | |
check_response(response) | |
return response | |
def check_task_for_label(task, label: str): | |
return label in task.labels | |
def remove_label(task, label_to_remove) -> bool: | |
if check_task_for_label(task, label_to_remove): | |
task.labels.remove(label_to_remove) | |
return True | |
return False | |
def add_label(task, new_label) -> bool: | |
if check_task_for_label(task, new_label): | |
return False | |
task.labels.append(new_label) | |
return True | |
def build_command_update_labels(task): | |
command = { | |
"type": "item_update", | |
"args": {"id": task.id, "labels": task.labels}, | |
"uuid": uuid.uuid4().hex, | |
} | |
return command | |
def bulk_update_labels(tasks) -> None: | |
max_batch_size = 99 | |
for i in range(0, len(tasks), max_batch_size): | |
commands = [] | |
batch = tasks[i : i + max_batch_size] | |
for task in batch: | |
command = build_command_update_labels(task) | |
commands.append(command) | |
body = {"commands": commands} | |
print(f"Attempting to update labels for a batch of {len(batch)} tasks...") | |
sync_post(body) | |
def bulk_update_labels_new(tasks, labels_to_add=None, labels_to_remove=None) -> None: | |
tasks_to_update = [] | |
for task in tasks: | |
labels_before = list(task.labels) | |
if labels_to_remove: | |
for label in labels_to_remove: | |
remove_label(task, label) | |
if labels_to_add: | |
for label in labels_to_add: | |
add_label(task, label) | |
if set(labels_before) != set(task.labels): | |
tasks_to_update.append(task) | |
if tasks_to_update: | |
print( | |
f"Attempting to update labels for {len(tasks_to_update)} tasks in total..." | |
) | |
bulk_update_labels(tasks=tasks_to_update) | |
def swap_labels() -> None: | |
label_to_remove = input("Enter the label to remove: ") | |
label_to_add = input("Enter the label to add: ") | |
tasks = todoist_api.get_tasks(filter=f"@{label_to_remove}") | |
if tasks: | |
bulk_update_labels_new( | |
tasks, | |
labels_to_remove=[label_to_remove], | |
labels_to_add=[label_to_add], | |
) | |
else: | |
raise ValueError(f"No tasks with @{label_to_remove} found!") | |
if __name__ == "__main__": | |
swap_labels() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment