Report de tarefas com Notion e ChatGPT

Já faz um tempo que uso o Notion para me organizar com minhas tarefas, anotações, estudos e projetos. Trabalho com o Notion aberto o tempo todo e lá faço anotações de reuniões, insiro tarefas e faço anotações sobre minhas prioridades e projetos. Também o uso constantemente enquanto estudo e planejo meus projetos pessoais, como este.

Com isso em mente, pensei que seria interessante criar algum sistema que me trouxesse algumas informações do meu Notion para o meu email diariamente. Dessa forma, eu teria essas informações dentro da mesma ferramenta onde organizo e consumo tantas informações importantes, como newsletters, resumos de projetos, emails pessoais e de trabalho, etc. Foi pensando nisso que criei a integração apresentada aqui, onde a ideia é trazer para minha caixa de email todos os dias as minhas tarefas com deadline mais próximo, ordenadas por data de entrega e prioridade. Achei que o ChatGPT poderia me ajudar com a priorização das tarefas, e dei um jeito de inseri-lo nesse fluxo de coleta e envio de tarefas.

Todo o projeto é aberto e pode ser encontrado em meu GitHub. Tenho planos de tornar o software mais fácil de usar, onde não existe a necessidade de mexer com código. Planos futuros 🙂

📝 Antes da automação, o Notion

Para que a automação funcione, é necessário que o Notion integrado ao projeto siga alguns padrões no controle de tarefas. O termo ‘Painel de Controle’ é simplesmente um nome para um dataset do Notion, que contém as tarefas a serem realizadas. Cada ‘Tarefa’ é uma entrada no dataset, e precisa conter as Colunas (campos): ‘Title’ (campo padrão), ‘Tags’, ‘Deadline’, ‘ASAP’ (checkbox) e ‘DONE’ (checkbox).

Abaixo temos um screenshot do meu Notion. Ele conta com vários outros datasets, regras de automação, ordenação e organização. Espero um dia poder contar e mostrar mais sobre ele.

🔐 Chaves de APIs

O software precisará de algumas chaves e IDs para funcionar corretamente. Siga este tutorial do próprio Notion para conseguir o DATASET_ID e a API_KEY e armezene esses valores no arquivo ‘.env’.

Usaremos também a API do Google GMail para enviar os emails diários de report, e precisamos criar as credenciais de serviço. Para isso, basta seguir o tutorial do próprio Google sobre o tema, encontrado aqui. Siga os passos para a criação de um projeto no Google Cloud, habilitação da API do Gmail e download das credenciais. Salve o arquivo na raiz do projeto como ‘credentials.json’.

Após seguir o processo de criação de credenciais da API do Gmail e autenticação, um arquivo ‘token.json’ deve ser criado na pasta do projeto.

Por último, precisaremos de uma chave de API da OpenAI, para poder chamar o ChatGPT via API. Esse serviço é pago, e os valores podem ser encontrados aqui. Para criar uma chave, basta estar logado no site da OpenAI e criar uma nova chave aqui. Um meio de pagamento precisa estar configurado na plataforma. Salvaremos essa chave de API no documento ‘.env’ na raiz do projeto.

🚀 It’s time to code

Todo o software foi feito usando a linguagem de programação Python, e abaixo explico algumas partes do projeto, para que fique claro como a integração foi feita.

Primeiro, precisamos chamar a API do Notion e coletar as tarefas presentes em nosso ‘Painel de Controle’. Para isso, vamos definir nossa Chave de API e ID do Dataset. Ambas são armazenadas no arquivo ‘.env’, na raiz do projeto, seguindo o seguinte formato:

OPENAI_KEY="sk-rmiH..."                            
EMAIL_FROM="example@gmail.com"                            
EMAIL_TO="example@gmail.com"                            
DISPLAY_NAME="Carlos"                            
NOTION_DATABASE_ID="8be43e..."                            
NOTION_API_KEY="secret_x0l..."         

Com os valores de Chave de API e ID do Dataset armazenados no arquivo JSON, o software irá carregar as credenciais e chamar a API para buscar as tarefas. O trecho de código abaixo é responsável por essa requisição. Vale ressaltar que todo o código está disponível no GitHub.

def collect_tasks_from_control_panel(n_days=7):
    """
    Connect to Notion API and collect Tasks from "Control Panel" database.
    """
    notion_credentials = load_notion_credentials()
    today = datetime.datetime.now()
    delta = datetime.timedelta(days=n_days)
    one_week = today + delta
    one_week = one_week.isoformat()

    url = "https://api.notion.com/v1/databases/" + \n        notion_credentials["database_id"] + "/query"

    payload = {
        "filter": {
            "and": [
                {
                    "property": "DONE",
                    "checkbox": {"equals": False},
                },
                {
                    "property": "Deadline",
                    "date": {"before": str(one_week)}
                }
            ]
        }
    }

    headers = {
        "accept": "application/json",
        "Authorization": "Bearer " + notion_credentials["api_key"] + "",
        "Notion-Version": "2022-06-28",
        "content-type": "application/json"
    }

    print("Collecting tasks from Notion...")

    response = requests.post(url, json=payload, headers=headers)

    data = json.loads(response.text)

    all_task_data = []

    for d in data["results"]:
        all_task_data.append(
            {
                "name": d["properties"]["Task"]["title"][0]["text"]["content"],
                "deadline": d["properties"]["Deadline"]["date"]["start"],
            }
        )

    sorted_tasks = sorted(all_task_data, key=lambda d: d["deadline"])

    print("Done.")
    return sorted_tasks

Com as tarefas recuperadas do Notion, precisamos agora enviar para o ChatGPT para que a AI faça a sua sugestão de priorização e estimativas de tempo. Para isso, eu envio as informações das tarefas via API dentro de um prompt que montei, mostrado no exemplo abaixo. Pretendo melhorá-lo, e utilizar o ChatGPT de mais formas neste projeto.

import os
import openai
from dotenv import load_dotenv


def call_openai_assistant(tasks):
    load_dotenv()
    openai.api_key = os.getenv("OPENAI_KEY")

    print("Calling ChatGPT. This can take a while...")

    completion = openai.ChatCompletion.create(
        model="gpt-3.5-turbo",
        messages=[
            {
                "role": "assistant",
                "content": build_message(tasks)
            }
        ]
    )

    answer = completion.choices[0].message.content
    return answer


def build_message(tasks):
    message = "Using few words, please help me to prioritize " + \ 
        "the following tasks. Answer in portuguese. Explain the " + \ 
        "importance of each one of the tasks and why they are " + \ 
        "piority or not when compared to the others. " + \ 
        "Also estimate the time to complete each one." + \ 
        "\n Instructions:" + \ 
        "\n- Be brief and explain the prioritization." + \ 
        "\n- Tasks are in portuguese." + \ 
        "\n- Answer with the format: #. <task_description> " + \ 
        "- (<explanation_about_importance>) - <time_estimation>" + \ 
        "\nTasks: "\ 

    for task in tasks:
        message += "\n - " + task["name"]

    return message

Como última parte do projeto, vamos montar o HTML e enviar via email para o usuário. Para enviar o email, vamos chamar a API do GMail, e para isso iremos contar com as credenciais salvas em ‘credentials.json’, na raiz do projeto. Também usei o  Jinja2 para montar o HTML. O HTML base que serve como template para o email pode ser encontrado na pasta ‘templates/’ do projeto.

O trecho de código abaixo mostra um pouco do processo para enviar o email com as tarefas.

def send_email_with_tasks(all_tasks, chatgpt_answer):
    """
    Considering a already created token.json file based on GCloud credentials,
    send an email using GMail API.
    """
    print("Sending email...")
    creds = Credentials.from_authorized_user_file("token.json", SCOPES)
    email_config = load_email_config()
    email_message = build_email_body(
        all_tasks,
        email_config["display_name"],
        chatgpt_answer
    )

    try:
        service = build("gmail", "v1", credentials=creds)
        message = MIMEText(email_message, "html")

        message["To"] = email_config["email_to"]
        message["From"] = email_config["email_from"]
        message["Subject"] = "My Notion Bot - Tasks"

        encoded_message = base64.urlsafe_b64encode(message.as_bytes()).decode()

        create_message = {
            "raw": encoded_message
        }

        send_message = (service.users().messages().send
                        (userId="me", body=create_message).execute())

        print("Done.")

    except HttpError as error:
        print(F"An error occurred: {error}")
        send_message = None

    return send_message

IMPORTANTE: as configurações de endereço de emails (tanto o ‘from’ quanto o ‘to’), bem como o nome do usuário que irá receber o report, podem ser inseridas e modificadas no arquivo ‘.env’.

🎯 Resumindo…

O repositório no GitHub contém as instruções mais diretas (e talvez mais completas) de como rodar o programa. Mas, tentando colocar de forma mais prática, este é o fluxo que deve ser seguido:

  1. Garanta que o ‘Painel de Controle’ no Notion esteja configurado corretamente, contendo os campos necessários.
  2. Preencha o arquivo ‘.env’ com as credenciais de Notion, Gmail e ChatGPT.
  3. Instale as bibliotecas Python necessárias presentes no ‘requirements.txt’.
  4. Execute o arquivo ‘run.py’.

Conclusão

Escrevi esse texto como forma de registro na construção de um pequeno software que já está me ajudando a me organizar melhor, e espero que esse registro possa funcionar também como fonte de conhecimento para outras pessoas. O sistema tem um propósito direto e simples, e se baseia no uso de tecnologias comuns e APIs bem consolidadas. Entretanto, isso não o torna menos relevante. Receber um resumo diário de tarefas e compromissos me ajuda e pode ajudar outras pessoas, e é isso que importa 😅.


Comments

Leave a Reply

Your email address will not be published. Required fields are marked *