Projeto que lê contatos no Supabase e envia, via Z-API, a mensagem "Olá {nome}, tudo bem com você?" para N contatos (padrão 3).
Inclui logs estruturados, testes unitários, Docker, CI (GitHub Actions) e Swagger (OpenAPI) para documentação.
src/
services/
supabase_client.py
zapi_client.py
utils/
logger.py
main.py # fluxo CLI: Supabase → Z-API
tests/ # pytest + respx
docs/openapi.yaml # documentação OpenAPI (Swagger)
Dockerfile
.github/workflows/ci.yml
requirements.txt
pytest.ini # silencia warnings e define addopts
setup.cfg # flake8 config
.env.example
Crie a tabela contacts e (se usar anon) habilite RLS + policy de leitura:
create table if not exists public.contacts (
id uuid primary key default gen_random_uuid(),
name text not null,
phone text not null,
active boolean not null default true,
created_at timestamptz not null default now()
);
alter table public.contacts enable row level security;
-- Para chave ANON: libera apenas SELECT
create policy "Allow read for anon" on public.contacts
for select
to anon
using (true);Dica: salve os números no formato E.164 só com dígitos (ex.:
5511999999999).
Copie o exemplo e edite:
cp .env.example .env.env (exemplo):
# Supabase
SUPABASE_URL=https://<project>.supabase.co
SUPABASE_ANON_KEY=eyJhbGci...
# Z-API
ZAPI_SEND_URL=https://api.z-api.io/instances/<INSTANCE_ID>/token/<TOKEN>/send-text
ZAPI_CLIENT_TOKEN=<CLIENT_TOKEN>
# App
MAX_CONTACTS=3
LOG_LEVEL=INFO
LOG_FILE=.logs/app.log
ZAPI_SEND_URLusa/send-text, payload{"phone":"5511...","message":"..."}e headerClient-Token(da aba Segurança).
python -m venv .venv
source .venv/bin/activate
python -m pip install -r requirements.txt
python -m src.maindocker build -t supabase-zapi .
docker run --env-file .env supabase-zapipython -m pip install -r requirements.txt
pytest --cov=src -q
flake8 src tests --max-line-length=88build_message()(mensagem exata)- Normalização do telefone (só dígitos)
- Envio via Z-API (mock HTTP com
respx, incluindo retry 5xx)
A especificação OpenAPI está em docs/openapi.yaml.
Visualizar:
- Acesse https://editor.swagger.io/
File → Import File→ selecionedocs/openapi.yaml
- Chave
anonvsservice_role:anonexige policy de leitura;service_roleignora RLS (não recomendado em produção). - Telefone: normalização para somente dígitos (Z-API
/send-textexige assim). - Retry: erros 5xx têm backoff exponencial (até 3 tentativas). 4xx não fazem retry.
- Logs: níveis via
.env, console e arquivo rotacionado.
MIT — veja o arquivo LICENSE.




