From 83ce95cf10fd9e9d581362453c558239d37ae06e Mon Sep 17 00:00:00 2001 From: Murilo Ijanc Date: Mon, 27 Jul 2026 20:46:40 -0300 Subject: Name the municipality when the CEP does not exist MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Answering only "não encontrei" wastes the trip. A CEP that fails is almost never a random number: it is someone who knows the city and guessed the rest, most often at the "-000" that 957 municipalities never received. The API now names that municipality on the 404, so the reply names it too. It stays an answer to a failure. No 📮, no address block, and no CEP suggested from inside the range — the range is sparse (Areal's 118 CEPs span nearly five thousand numbers), so the reply gives the count and says so instead of letting the two ends read as a list of valid CEPs. cep.is/go v0.1.0 discards the 404 body, so internal/lookup reads it with one extra GET, on that path alone and never inside a retry. Everything that can go wrong there — a slow answer, broken JSON, a faixa naming no municipality — falls back to the reply the bot has always given. The wrapper goes away the day the library exposes the field. --- internal/app/app.go | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) (limited to 'internal/app/app.go') diff --git a/internal/app/app.go b/internal/app/app.go index 0b78baf..ccb8483 100644 --- a/internal/app/app.go +++ b/internal/app/app.go @@ -15,6 +15,7 @@ import ( "cep.is/telegrambot/internal/bot" "cep.is/telegrambot/internal/config" + "cep.is/telegrambot/internal/lookup" "cep.is/telegrambot/internal/telegram" ) @@ -34,22 +35,28 @@ type App struct { // The whole-call timeout of the cep.is client is the shutdown grace on purpose: // handling one update is what a termination signal waits for, so a lookup must // not be allowed to outlast that budget. +// +// The client goes to the bot wrapped in [lookup.Client], which is what keeps the +// municipality the API names on a 404. The wrapper has its own short timeout, +// deliberately far below the grace: it is a footnote on an answer that is +// already writable. func New(ctx context.Context, cfg config.Config, logger *slog.Logger) (*App, error) { if logger == nil { logger = slog.Default() } - lookups, err := cepis.New( + cepisClient, err := cepis.New( cepis.WithBaseURL(cfg.CepisBaseURL), cepis.WithTimeout(cfg.RequestTimeout), cepis.WithMaxAttempts(cfg.MaxAttempts), cepis.WithBackoff(cfg.BackoffBase, cfg.BackoffMax), cepis.WithTotalTimeout(cfg.ShutdownGrace), - cepis.WithUserAgent("cepis-telegram/0.1.0 (+https://cep.is)"), + cepis.WithUserAgent("cepis-telegram/0.2.0 (+https://cep.is)"), ) if err != nil { return nil, fmt.Errorf("app: cep.is client: %w", err) } + lookups := lookup.New(cepisClient) api, err := telegram.New(cfg.Token, telegram.WithBaseURL(cfg.TelegramAPIBaseURL), -- cgit v1.3