From the department of things I wouldn't have bothered with a year ago, here's a python script to set Todoist label colors.
Why? I like a productivity environment with some color and flare, and it also helps to visually recognize what a task relates to. But setting label colors is more clicks than I have patience for.
How? Just figure out embeddings for each available color and then for each label. Use cosine similarity to set the color that best suits each label. Colors will stay consistent for existing labels and new ones will get just a dash of semantic meaning in their assignments.
Here's the code (you need an OpenAI API key and a Todoist API token set as environment variables):
import os
from todoist_api_python.api import TodoistAPI
from openai import OpenAI
import numpy as np
# Todoist palette colors from https://developer.todoist.com/api/v1#tag/Colors
colors = [
{"id": 30, "name": "berry_red", "hex": "#B8255F"},
{"id": 31, "name": "red", "hex": "#DC4C3E"},
{"id": 32, "name": "orange", "hex": "#C77100"},
{"id": 33, "name": "yellow", "hex": "#B29104"},
{"id": 34, "name": "olive_green", "hex": "#949C31"},
{"id": 35, "name": "lime_green", "hex": "#65A33A"},
{"id": 36, "name": "green", "hex": "#369307"},
{"id": 37, "name": "mint_green", "hex": "#42A393"},
{"id": 38, "name": "teal", "hex": "#148FAD"},
{"id": 39, "name": "sky_blue", "hex": "#319DC0"},
{"id": 40, "name": "light_blue", "hex": "#6988A4"},
{"id": 41, "name": "blue", "hex": "#4180FF"},
{"id": 42, "name": "grape", "hex": "#692EC2"},
{"id": 43, "name": "violet", "hex": "#CA3FEE"},
{"id": 44, "name": "lavender", "hex": "#A4698C"},
{"id": 45, "name": "magenta", "hex": "#E05095"},
{"id": 46, "name": "salmon", "hex": "#C9766F"},
#{"id": 47, "name": "charcoal", "hex": "#808080"},
#{"id": 48, "name": "grey", "hex": "#999999"},
{"id": 49, "name": "taupe", "hex": "#8F7A69"},
]
# OpenAI Client
oai = OpenAI()
# Embedding helper
def get_embedding(text):
# Replace underscores and hyphens with spaces
formatted_text = text.replace('_', ' ').replace('-', ' ')
response = oai.embeddings.create(
input=formatted_text,
model="text-embedding-3-small"
)
return response.data[0].embedding
# Add embeddings to each color in the colors list
print("Generating embeddings for colors...")
for color in colors:
color["embedding"] = get_embedding(color["name"])
# Get API token from environment variable for security
# You need to set this environment variable with your Todoist API token
api_token = os.environ.get("TODOIST_API_TOKEN")
if not api_token:
print("Error: TODOIST_API_TOKEN environment variable not set")
exit(1)
# Initialize the Todoist API client
api = TodoistAPI(api_token)
try:
# Get all labels
labels = api.get_labels()
for label_iter in labels:
for label in label_iter:
embedding = get_embedding(label.name)
# Fix the calculation of similarities - create a proper comparison array
color_embeddings = np.array([color["embedding"] for color in colors])
# Calculate similarities correctly - each embedding is a 1536-dim vector
similarities = np.array([np.dot(embedding, color_embedding) /
(np.linalg.norm(embedding) * np.linalg.norm(color_embedding))
for color_embedding in color_embeddings])
# Find the color with the highest similarity
max_index = np.argmax(similarities)
new_color = colors[max_index]["name"]
print(f"Setting {label.name} to {new_color}")
api.update_label(
label_id=label.id,
color=new_color
)
except Exception as error:
print(f"Error: {error}")
Add Comment
All comments are moderated. Your email address is used to display a Gravatar and optionally for notification of new comments and to sign up for the newsletter.