Skip to content

duducp/patofinance

Repository files navigation

Bot de Controle Financeiro via Telegram

Finanças Bot

📊 Gerencie suas finanças pessoais diretamente no Telegram

Registre gastos e receitas, veja extratos, saldo e resumo por categoria com comandos simples ou linguagem natural. Suporta grupos personalizados, categorias e tags para organizar tudo.

Deno TypeScript Supabase DeepSeek MIT CI Vercel


✨ Sobre

Assistente de finanças pessoais — registre gastos e receitas com comandos ou linguagem natural.

🎯 Funcionalidades

  • 💸 Registrar despesas/despesa 50 mercado ou "gastei 50 no almoço"
  • 💰 Registrar receitas/receita 3000 salário ou "recebi 3000 de salário"
  • 📊 Saldo do período/saldo, /saldo mes passado, /saldo janeiro
  • 📋 Extrato interativo/extrato com painel de filtros (categoria, grupo, tags, tipo, período), paginação e visualização otimizada
  • ⏳ Transações agendadas/agendadas lista todas as transações futuras
  • 🔄 Recorrências/recorrencia cria, adianta, pula, arquiva e edita recorrências com wizard de 8 passos + geração automática via cron diário
  • 🔍 Busca textual/buscar mercado encontra transações pela descrição, valor ou tag
  • 📈 Resumo por categoria/resumo com totais agrupados
  • 📁 Grupos (contas) — Organize por conta bancária, cartão de crédito, etc.
  • 🏷️ Categorias — Pré-definidas + personalizadas
  • 🔖 Tags livres — Adicione tags a transações (#trabalho #presente)
  • 🗣️ Wizard conversacional — O bot guia você passo a passo com botões interativos
  • 🧹 Limpeza automática — Remova categorias/grupos sem uso
  • 🌐 Linguagem natural — Digite frases como "quanto gastei esse mês?" ou "últimas 10 transações"
  • 🔑 Login no dashboard web/login gera código temporário de 6 dígitos para acessar o web dashboard

Arquitetura

Telegram → Edge Function (webhook) → Supabase DB → Resposta via Bot API
  • bot-core (Edge Function) — Webhook principal que processa mensagens, callbacks e wizards do Telegram
  • auth-telegram (Edge Function) — Valida códigos de login do dashboard web e cria sessões no Supabase Auth
  • Supabase DB — PostgreSQL com 11 tabelas
  • Bot API — Envia respostas com botões interativos

Tecnologias

  • Runtime: Deno (Supabase Edge Functions)
  • Banco: PostgreSQL + pg_trgm (Supabase)
  • API: Telegram Bot API
  • Linguagem: TypeScript
  • IA: DeepSeek API (para linguagem natural)

Estrutura do Projeto

finance/
├── Makefile                 # Comandos de desenvolvimento
├── AGENTS.md                # Guia de desenvolvimento + callbacks
├── CLAUDE.md                # Memory para IA
├── picture.png              # Foto de perfil do bot
├── supabase/
│   ├── config.toml          # Config local (verify_jwt=false)
│   ├── .env.example         # Template de variáveis de ambiente
│   ├── migrations/          # 24 migrations SQL
│   │   ├── 20260614000000_initial_schema.sql
│   │   ├── 20260614000001_add_wizard_steps.sql
│   │   ├── 20260614000002_add_wizard_steps_index_and_timestamps.sql
│   │   ├── 20260615000000_add_tags_step_to_receita_wizard.sql
│   │   ├── 20260615000001_add_normalized_name_and_trgm.sql
│   │   ├── 20260615000002_add_category_type.sql
│   │   ├── 20260615000003_add_session_seq.sql
│   │   ├── 20260615000004_add_wizard_step_options.sql
│   │   ├── 20260615000005_sync_existing_categories_type.sql
│   │   ├── 20260615000006_fix_normalize_string.sql
│   │   ├── 20260616000000_make_predefined_global.sql
│   │   ├── 20260616000001_create_user_sessions.sql
│   │   ├── 20260616000002_add_description_step.sql
│   │   ├── 20260616000003_fix_description_prompt_newlines.sql
│   │   ├── 20260616000004_separate_telegram_accounts.sql
│   │   ├── 20260616000005_add_search_index.sql
│   │   ├── 20260617000000_add_rls_policies.sql
│   │   ├── 20260617000001_add_link_codes.sql
│   │   ├── 20260617000002_add_auth_id_to_users.sql
│   │   ├── 20260617000003_add_link_codes_cleanup_cron.sql
│   │   ├── 20260617000004_grant_link_codes_to_authenticated.sql
│   │   ├── 20260618000000_remove_link_codes_direction.sql
│   │   ├── 20260618000001_add_recurrences.sql
│   │   └── 20260618000002_add_recorrencia_type_options.sql
├── functions/bot-core/
│   ├── index.ts            # Entry point + roteamento
│   ├── config.ts           # Env vars + cache NL
│   ├── types/index.ts      # Interfaces TypeScript
│   ├── utils/              # formatting, rate-limiter, dates, command-parsing, session, help-texts
│   ├── services/           # database, telegram, deepseek
│   └── handlers/           # commands, callbacks, recurrences, statement, management, wizard, nl-processing, queries
├── functions/auth-telegram/  # Edge Function for web login code validation
│   ├── index.ts            # POST /code → valida código, cria sessão Supabase Auth
│   └── config.ts           # Env vars
└── README.md

💡 Para um guia detalhado de desenvolvimento, consulte AGENTS.md.

Banco de Dados

Tabelas

Tabela Descrição
users Contas dos usuários (desacoplado de plataformas)
telegram_accounts Identidades Telegram vinculadas a users (telegram_id, username, first_name)
groups Grupos/contas bancárias (name, is_default)
categories Categorias (name, is_predefined, normalized_name, transaction_type)
transactions Receitas e despesas (type, amount, tags TEXT[])
wizard_states Estado do wizard conversacional + session_seq (TTL 10min)
wizard_steps Steps configuráveis dos wizards
wizard_step_options Opções de seleção para cada step
predefined_categories Categorias padrão com tipo (expense/income/null=ambos)
recurrences Recorrências com tipo de frequência, intervalo, próxima data, arquivamento
notification_queue Erros enfileirados pelo cron de recorrências para notificar o usuário
user_sessions Sessões de callback (session_seq para proteção contra replay)
link_codes Códigos de 6 dígitos para autenticação Telegram→Web. Bot gera, dashboard valida

Extensões

  • pg_trgm — Similaridade fuzzy entre nomes via trigramas (usado em suggest_categories, suggest_groups, suggest_tags)
  • pg_cron — Agendador de tarefas (executa process_recurrences() diariamente às 06:00 BRT)

Categorias Pré-definidas

Separadas por tipo de transação:

💸 Despesa: Alimentação · Moradia · Transporte · Saúde · Educação · Lazer · Vestuário · Contas 💰 Receita: Salário · Freela · Investimentos · Benefícios 🔄 Ambos: Outros

Configuração

1. Criar Bot no Telegram

  1. Abra o Telegram e procure por @BotFather
  2. Envie /newbot
  3. Escolha um nome para o bot (ex: "Meu Bot Financeiro")
  4. Escolha um username (ex: meubotfinanceiro_bot)
  5. Copie o token fornecido (formato: 123456789:ABCdefGHIjklMNOpqrsTUVwxyz)

2. Configurar Supabase

  1. Acesse supabase.com e faça login
  2. Crie um novo projeto ou use um existente
  3. Vá em Project Settings > API e copie:
    • Project URL (ex: https://xyzproject.supabase.co)
    • Service Role Key (eyJ...)

3. Instalar Supabase CLI

# macOS
brew install supabase/tap/supabase

# Linux
npx supabase --version

4. Fazer Login no Supabase

supabase login --token seu_token_de_acesso

Para obter o token:

  1. Acesse supabase.com/dashboard/account/tokens
  2. Crie um novo token

5. Linkar ao Projeto

supabase link --project-ref seu_project_ref

O project_ref está na URL do projeto: https://seu_project_ref.supabase.co

6. Aplicar Migrações

supabase db push

7. Configurar Variáveis de Ambiente

Todas as variáveis de ambiente estão documentadas em supabase/functions/.env.example.

Produção

supabase secrets set TELEGRAM_BOT_TOKEN=seu_token_do_bot
supabase secrets set TELEGRAM_SECRET_TOKEN=seu_secret_token
supabase secrets set DEEPSEEK_API_KEY=sua_chave_deepseek  # opcional, mas recomendado

Local

# Copie o template e preencha
cp supabase/functions/.env.example supabase/functions/.env
# Edite .env com seus valores

# Ou exporte manualmente:
supabase status  # obter SUPABASE_ANON_KEY e SUPABASE_URL

export SUPABASE_ANON_KEY="sua_anon_key_aqui"
export TELEGRAM_SECRET_TOKEN="seu_secret_token_aqui"

make dev-test-start
make dev-test-gasto

Resumo das variáveis:

Variável Obrigatória Descrição
TELEGRAM_BOT_TOKEN ✅ Sim Token do @BotFather
TELEGRAM_SECRET_TOKEN ✅ Sim Token de verificação do webhook
SUPABASE_URL Automático URL interna do Supabase (http://kong:8000 local)
SUPABASE_SERVICE_ROLE_KEY Automático Chave service role (bypass RLS)
DEEPSEEK_API_KEY ❌ Não API key para linguagem natural (sem ela, só comandos)

Importante: O secret_token deve conter apenas letras, números, underscores e hífens.

8. Deploy da Edge Function

supabase functions deploy bot-core --no-verify-jwt

9. Configurar Webhook no Telegram

curl -X POST "https://api.telegram.org/botSEU_TOKEN/setWebhook" \
  -H "Content-Type: application/json" \
  -d '{"url": "https://seu_project_ref.supabase.co/functions/v1/bot-core", "secret_token": "seu_secret_token"}'

10. Verificar Webhook

curl "https://api.telegram.org/botSEU_TOKEN/getWebhookInfo"

Resposta esperada:

{
  "ok": true,
  "result": {
    "url": "https://seu_project_ref.supabase.co/functions/v1/bot-core",
    "pending_update_count": 0
  }
}

11. Configurar Comandos no BotFather

  1. Procure @BotFather no Telegram
  2. Envie /setcommands
  3. Selecione seu bot
  4. Cole:
despesa - Registrar despesa (ex: /despesa 50 mercado)
receita - Registrar receita (ex: /receita 3000 salario)
saldo - Ver saldo (ex: /saldo mes passado)
extrato - Ver extrato (ex: /extrato janeiro 2025)
agendadas - Listar transacoes futuras agendadas
recorrencia - Gerenciar recorrencias (criar, adiantar, pular, arquivar)
buscar - Buscar transacoes por palavra-chave
resumo - Resumo por categoria (ex: /resumo ultimo mes)
detalhes - Detalhes, edicao e exclusao de transacao
categoria - Gerenciar categorias
grupo - Gerenciar grupos
tag - Gerenciar tags
limpar - Remover categorias/grupos sem transacoes
cancelar - Cancelar operacao em andamento
resetar - Resetar conta (apaga todos os dados)
login - Gerar codigo para acessar o dashboard web
ajuda - Ajuda completa

Description (info do bot)

Gerencie suas finanças pessoais diretamente no Telegram. Registre gastos e receitas, veja extratos, saldo e resumo por categoria com comandos simples ou linguagem natural. Suporta grupos personalizados, categorias e tags para organizar tudo.

About (texto inicial do chat)

Assistente de finanças pessoais — registre gastos e receitas com comandos ou linguagem natural.

Comandos

💰 Financeiros

Comando Descrição Exemplo
/despesa Registrar despesa /despesa 50 mercado
/receita Registrar receita /receita 3000 salario
/saldo Saldo do período /saldo, /saldo mes passado, /saldo janeiro
/extrato Extrato interativo — painel de filtros + paginação /extrato, /extrato janeiro 2025, /extrato --grupo Pessoal
/agendadas Listar transações futuras agendadas /agendadas
/recorrencia Gerenciar recorrências (criar, listar, adiantar, pular, arquivar) /recorrencia
/buscar Buscar transações por palavra-chave na descrição /buscar mercado
/resumo Resumo por categoria /resumo, /resumo ultimo mes, /resumo --grupo Trabalho
/detalhes Detalhes, edição e exclusão da transação pelo ID /detalhes 42

📁 Organização

Comando Descrição Exemplo
/categoria Listar ou criar categorias /categoria, /categoria Transporte
/grupo Listar ou criar grupos /grupo, /grupo Nubank
/tag Listar tags com contagens + botões /tag

⚙️ Utilitários

Comando Descrição
/limpar Remover categorias/grupos sem transações
/resetar Resetar conta (apaga todas as transações, categorias, grupos e tags)
/cancelar Cancelar operação em andamento
/login Gerar código de 6 dígitos para acessar o dashboard web
/ajuda Ajuda completa. Use /ajuda <comando> para detalhes (ex: /ajuda saldo)
/futuras Listar transações agendadas (alias: /agendadas)

🌐 Linguagem Natural

Com DEEPSEEK_API_KEY configurada, você pode digitar frases diretamente ou usar períodos naturais nos comandos:

  • "gastei 50 no almoço" — registra despesa
  • "recebi 3000 de salário" — registra receita
  • "quanto tenho?" — saldo do mês
  • "quanto gastei em alimentação?" — consulta por categoria
  • "resumo do mês" — resumo agrupado
  • "últimas 10 transações" — extrato
  • "agendadas" — lista transações futuras
  • "busque por mercado" — busca transações pela descrição
  • "crie a categoria transporte" — criar categoria
  • "transações com #alimentação" — filtrar por tag
  • "quais tags uso?" — listar tags
  • "limpe categorias sem uso" — limpeza
  • "crie uma recorrência do aluguel" — criar recorrência
  • "mostre recorrências" — listar recorrências

Período natural nos comandos:

Comando Descrição
/saldo mes passado Saldo do mês anterior
/saldo janeiro Saldo de janeiro
/saldo semana passada Saldo da semana passada
/saldo ontem Saldo de ontem
/extrato janeiro 2025 Extrato de janeiro de 2025
/extrato --grupo Pessoal Extrato filtrado por grupo
/resumo ultimo mes Resumo do mês passado
/resumo --grupo Trabalho Resumo filtrado por grupo
/agendadas Lista transações futuras agendadas
/buscar mercado Busca transações com "mercado" na descrição
/buscar #ifood Busca transações com a tag #ifood
/buscar 150 Busca transações com valor R$ 150

Sem a chave DeepSeek, apenas comandos / funcionam.

Flags Suportadas

Flag Descrição Exemplo
--grupo Nome Vincular a um grupo específico /despesa 50 --grupo Nubank
--data DD/MM/AAAA Data personalizada /despesa 50 --data 15/01/2024
#tag Adicionar tags (múltiplas) /despesa 50 #comida #lazer
Texto livre Define a categoria /despesa 50 mercado → categoria "mercado"

Exemplos:

/despesa 50 mercado --grupo Pessoal #almoço
/despesa 100 vestuário --data 15/01/2024 #presente
/despesa 50 Nubank --grupo Nubank #transporte
/receita 3000 salário --grupo Nubank

Wizard Conversacional

Quando você digita apenas /despesa (sem argumentos), o bot guia passo a passo. Cada resposta sua é confirmada editando a mensagem do prompt com um ✅ e a mensagem digitada é removida — o chat fica limpo e organizado:

Usuário: /despesa
Bot: 💸 Quanto você gastou? Informe o valor:
Usuário: 50
     (a mensagem do prompt muda para: ✅ 💰 Valor: R$ 50,00)
     (a mensagem "50" é apagada)
Bot: 📝 Descrição (opcional)?
     [⏭️ Pular]
Usuário: clica em "⏭️ Pular"
     (a mensagem muda para: ✅ 📝 Descrição: Nenhuma descrição informada)
Bot: 🏷️ Qual categoria?
     [Alimentação] [Transporte] [Saúde] [✏️ Nova]
Usuário: clica em "Alimentação"
     (a mensagem muda para: ✅ 🏷️ Categoria: Alimentação)
Bot: 📁 Qual grupo?
     [Pessoal] [Nubank] [Inter]
Usuário: clica em "Pessoal"
     (a mensagem muda para: ✅ 📁 Grupo: Pessoal)
Bot: 📅 Qual data?
     [📅 Hoje] [📅 Ontem] [📆 Outra data]
Usuário: clica em "📅 Hoje"
     (a mensagem muda para: ✅ 📅 Data: 15/07/2026)
Bot: 🔖 Tags? (ex: #trabalho)
     [#comida] [#lazer] [✅ Concluir] [⏭️ Pular]
Usuário: clica em "⏭️ Pular"
     (a mensagem muda para: ✅ 🔖 Tags: Nenhuma tag)
Bot: ✅ Despesa registrada com sucesso!

     🆔 ID: #42
     💰 Valor: R$ 50,00
     🏷️ Categoria: Alimentação
     📁 Grupo: Pessoal
     📅 Data: 15/07/2026

     [🔍 Ver detalhes] [🔄 Transformar em recorrência]

Resumo das confirmações visuais por step:

Step Input Confirmação
Valor digita número ✅ 💰 Valor: R$ 50,00
Descrição digita / Pular ✅ 📝 Descrição: ... / Nenhuma descrição informada
Categoria clica / digita nova ✅ 🏷️ Categoria: Alimentação
Grupo clica / digita novo ✅ 📁 Grupo: Pessoal
Data clica Hoje/Ontem / Outra ✅ 📅 Data: 15/07/2026
Tags digita / Concluir / Pular re-render in-place / ✅ 🔖 Tags: #tag1 #tag2 / Nenhuma tag

💡 O mesmo padrão se aplica ao wizard de recorrências (/recorrencia), incluindo frequência: ✅ 🔄 Frequência: A cada 15 dias / Mensal (dia 15) / Anual (15 de Jan).

Linguagem Natural com Follow-up

Se você usa uma frase como "gastei 50 no almoço", o bot extrai o que consegue e pergunta só o que falta:

Usuário: "gastei 50 no almoço"
Bot: (extrai amount=50, description="almoço")
     🏷️ Em que categoria?
     [Alimentação] [Transporte] [Saúde] [✏️ Nova]
Usuário: clica em "Alimentação"
Bot: 📁 Em que grupo? (só pergunta se houver mais de 1 grupo)
     [Pessoal] [Nubank] [Inter]
     [⏭️ Pular]
Usuário: clica em "Pessoal"
Bot: ✅ Despesa registrada com sucesso!

     🆔 ID: #43
     💰 Valor: R$ 50,00
     📝 Descrição: almoço
     🏷️ Categoria: Alimentação
     📁 Grupo: Pessoal
     📅 Data: 15/07/2026

     [🔍 Ver detalhes] [🔄 Transformar em recorrência]

Desenvolvimento Local

Iniciar Supabase Local

supabase start

Testar Edge Function

curl -X POST http://127.0.0.1:54321/functions/v1/bot-core \
  -H "Content-Type: application/json" \
  -H "apikey: sua_anon_key" \
  -H "X-Telegram-Bot-Api-Secret-Token: seu_secret_token" \
  -d '{"update_id": 1, "message": {"message_id": 1, "from": {"id": 123, "first_name": "Test"}, "chat": {"id": 123, "type": "private"}, "date": 1234567890, "text": "/start"}}'

Parar Supabase

supabase stop

Troubleshooting

Erro 401 Unauthorized

O secret token no Telegram não bate com o do Supabase:

# Atualizar secret no Supabase
supabase secrets set TELEGRAM_SECRET_TOKEN=novo_token

# Atualizar webhook no Telegram
curl -X POST "https://api.telegram.org/botSEU_TOKEN/setWebhook" \
  -H "Content-Type: application/json" \
  -d '{"url": "https://seu_project_ref.supabase.co/functions/v1/bot-core", "secret_token": "novo_token"}'

# Redeploy
supabase functions deploy bot-core --no-verify-jwt

Bot não responde

  1. Verifique o webhook: curl "https://api.telegram.org/botSEU_TOKEN/getWebhookInfo"
  2. Verifique se pending_update_count está em 0
  3. Verifique os logs no Supabase Dashboard > Edge Functions > bot-core

Erro de permissão no banco

Verifique se as migrations foram aplicadas:

supabase db push

Roadmap

🗺️ Veja o ROADMAP.md para a visão completa do que já foi implementado e dos próximos passos.

✅ Já implementado: CRUD financeiro, NL com DeepSeek, busca por descrição/valor/tag, extrato com filtros, paginação, wizard conversacional, categorias/grupos/tags, /agendadas, edição/exclusão, recorrências (wizard + advance/skip/archive/edit + cron automático), login no web dashboard.

📋 Próximos: Exportação CSV, orçamentos mensais, gráficos por categoria, web dashboard.

Licença

MIT

About

Gerencie suas finanças pessoais diretamente no Telegram

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors