coda/README.md
Rodrigo Verdiani 2fd56d0f36 fix(webhook): rename route from /webhook/lidarr to /webhook
Simplify the webhook endpoint path to match the URL documented
in the Lidarr integration guide.

Also add a Lidarr integration section to README covering Coda
environment variables, Lidarr webhook configuration, and the
full end-to-end flow.
2026-07-06 22:50:30 -03:00

174 lines
7.7 KiB
Markdown

# Coda
Transcoder para Lidarr, escrito em Go e distribuído via Docker. Converte álbuns de **FLAC** para **MP3 320 kbps CBR**, acionado automaticamente por webhooks do Lidarr ou manualmente pela interface web.
Em ambos os fluxos, o Coda converte os arquivos, valida o resultado, remove os FLACs originais e solicita ao Lidarr um rescan da biblioteca.
## Funcionalidades
- Conversão FLAC → MP3 320 kbps CBR (libmp3lame), preservando metadados e capa.
- Acionamento por **webhook** do Lidarr ou **manual** pela interface web.
- Fila interna com worker pool e conversão paralela configurável.
- Validação pós-conversão (ffprobe, tamanho, existência) antes de apagar qualquer FLAC.
- **Janela de trabalho** opcional (desabilitada por padrão) para restringir o processamento a um intervalo de horário.
- Interface web: dashboard, tarefas, logs, navegação/scan de FLACs e configurações.
- Persistência em **SQLite** (jobs, logs e configurações).
- Modo **dry run** para simular sem converter nem apagar.
- Notificações via **ntfy** (self-hosted ou público) ao final de cada job.
## Stack
| Camada | Escolha |
|--------------|------------------------------------|
| Linguagem | Go 1.25.x |
| HTTP Router | chi (go-chi/chi/v5) |
| Banco | SQLite (modernc.org/sqlite, sem CGO) |
| UI | html/template + htmx + Tailwind CSS v4 + DaisyUI |
| Logging | log/slog (stdlib) + handler SQLite |
| Áudio | ffmpeg + ffprobe (libmp3lame) |
| Distribuição | Docker (Alpine Linux) |
## Início Rápido (local, sem Docker)
Pré-requisitos: **Go 1.25+** e **ffmpeg** com `libmp3lame`.
No Fedora, o ffmpeg completo vem do RPM Fusion:
```bash
sudo dnf install -y https://mirrors.rpmfusion.org/free/fedora/rpmfusion-free-release-$(rpm -E %fedora).noarch.rpm
sudo dnf install -y ffmpeg
```
Setup e execução:
```bash
make setup # baixa Tailwind + DaisyUI + htmx, deps Go, cria .env
mkdir -p data testdata/music # pastas locais (ajuste MUSIC_PATH no .env)
make run # dev com hot-reload (http://localhost:8080)
```
O SQLite **não** precisa ser instalado (`modernc.org/sqlite` é Go puro).
## Comandos (Makefile)
```bash
make setup # baixa ferramentas + deps + cria .env
make css # gera web/static/app.css
make css-watch # regenera o CSS ao salvar (dev)
make run # dev (build tag dev, assets do disco, hot-reload)
make run-prod # produção (assets embutidos via //go:embed)
make build # binário de produção em bin/server
make test # go test ./...
make lint # go vet ./...
make clean # remove bin/ e app.css
```
## Docker
```bash
docker build -t coda .
docker run -d \
-p 8080:8080 \
-v /caminho/para/musica:/music \
-v coda-data:/data \
-e LIDARR_URL=http://lidarr:8686 \
-e LIDARR_API_KEY=... \
coda
```
Volumes:
- **`/music`** — arquivos de música (mesmo path usado pelo Lidarr).
- **`/data`** — volume persistente do SQLite (`coda.db`).
## Configuração
Definida por variáveis de ambiente (defaults) e sobrescrita pela interface web (persistida no SQLite; a web vence). Em dev, o `.env` é carregado no startup.
| Variável | Default | Descrição |
|-----------------------|--------------------|----------------------------------------|
| `PORT` | `8080` | Porta do servidor HTTP |
| `WORKERS` | `4` | Workers simultâneos |
| `FFMPEG_BIN` | `/usr/bin/ffmpeg` | Caminho do ffmpeg |
| `FFPROBE_BIN` | `/usr/bin/ffprobe` | Caminho do ffprobe |
| `LOG_LEVEL` | `INFO` | Nível de log |
| `DRY_RUN` | `false` | Não converte nem apaga (só registra) |
| `LIDARR_URL` | — | URL base do Lidarr |
| `LIDARR_API_KEY` | — | API key do Lidarr |
| `WEBHOOK_SECRET` | — | Segredo para validar webhooks |
| `MUSIC_PATH` | `/music` | Diretório com os arquivos de música |
| `DB_PATH` | `/data/coda.db` | Caminho do arquivo SQLite |
| `TIMEZONE` | `UTC` | Timezone da janela de trabalho |
| `WORK_WINDOW_ENABLED` | `false` | Habilita a janela de trabalho |
| `WORK_WINDOW_START` | `08:00` | Início da janela (HH:MM) |
| `WORK_WINDOW_END` | `18:00` | Fim da janela (HH:MM) |
| `NTFY_ENABLED` | `false` | Habilita notificações ntfy |
| `NTFY_URL` | — | URL base do servidor ntfy |
| `NTFY_TOPIC` | — | Tópico para publicar notificações |
| `NTFY_TOKEN` | — | Token de autenticação (opcional) |
## Integração com o Lidarr
O Coda funciona como um pós-processador do Lidarr. Após o Lidarr importar um álbum, ele dispara um webhook para o Coda, que converte os FLACs para MP3 e solicita um rescan da biblioteca.
### Pré-requisito: paths compartilhados
O Lidarr e o Coda precisam enxergar a biblioteca no **mesmo caminho absoluto**. Se o Lidarr acessa os arquivos em `/music`, o Coda também deve ter `/music` montado apontando para o mesmo diretório físico.
### 1. Configurar o Coda
Defina as variáveis de ambiente (ou configure via `/settings` na interface web):
| Variável | Descrição |
|------------------|--------------------------------------------------------|
| `LIDARR_URL` | URL base do Lidarr, ex: `http://lidarr:8686` |
| `LIDARR_API_KEY` | API key do Lidarr (**Settings → General → API Key**) |
| `WEBHOOK_SECRET` | Segredo para validar webhooks (opcional, mas recomendado) |
| `MUSIC_PATH` | Caminho raiz da biblioteca, deve coincidir com o Lidarr |
### 2. Configurar o Webhook no Lidarr
No Lidarr, acesse **Settings → Connect → + → Webhook** e configure:
| Campo | Valor |
|------------------------|----------------------------------------------|
| **Name** | Coda (ou qualquer nome) |
| **Notification Triggers** | `On Release Import` |
| **URL** | `http://<host-do-coda>:8080/webhook` |
| **Method** | POST |
Se `WEBHOOK_SECRET` estiver definido, adicione um header:
| Header | Valor |
|---------------------|------------------|
| `X-Webhook-Secret` | `<seu-secret>` |
Salve e clique em **Test** para validar. O Coda responderá com `{"status":"ok"}`.
### Fluxo completo
```
Lidarr importa álbum FLAC
→ POST /webhook (Lidarr → Coda)
→ Coda enfileira job
→ Worker converte FLAC → MP3, valida, remove FLACs
→ Coda chama API do Lidarr para rescan da pasta
→ Lidarr detecta os MP3s e atualiza a biblioteca
```
## Estrutura do Projeto
```
cmd/server/ # entrypoint
internal/ # config, scheduler, webhook, queue, worker,
# transcoder, validator, lidarr, logger, web,
# models, store, scanner, ntfy
web/ # styles/ (fonte CSS), static/ (gerado), templates/
data/ # volume local do SQLite
```
## Documentação
- [Requisitos](docs/requirements.md)
- [Arquitetura](docs/architecture.md)
- [AGENTS.md](AGENTS.md) — guia para agentes e convenções do projeto