Files
telegram-gateway/server.go
Gabriel Radureau ee832de089
All checks were successful
Docker Build / build-and-push-image (push) Successful in 1m8s
Phase 1 MVP — echo bot factory
2026-05-09 12:23:59 +02:00

76 lines
1.7 KiB
Go

package main
import (
"encoding/json"
"fmt"
"log"
"net/http"
"strings"
)
type Server struct {
registry *Registry
}
func NewServer(r *Registry) *Server {
return &Server{registry: r}
}
func (s *Server) Routes() http.Handler {
mux := http.NewServeMux()
mux.HandleFunc("/healthz", s.health)
mux.HandleFunc("/readyz", s.ready)
mux.HandleFunc("/bot/", s.botWebhook)
return chain(mux, recoverMW, accessLogMW)
}
func (s *Server) health(w http.ResponseWriter, _ *http.Request) {
w.WriteHeader(http.StatusOK)
_, _ = fmt.Fprint(w, "OK")
}
func (s *Server) ready(w http.ResponseWriter, _ *http.Request) {
w.WriteHeader(http.StatusOK)
_, _ = fmt.Fprint(w, "OK")
}
func (s *Server) botWebhook(w http.ResponseWriter, r *http.Request) {
if r.Method != http.MethodPost {
http.Error(w, "method not allowed", http.StatusMethodNotAllowed)
return
}
slug := strings.TrimPrefix(r.URL.Path, "/bot/")
slug = strings.Trim(slug, "/")
if slug == "" || strings.Contains(slug, "/") {
http.Error(w, "bot slug missing or malformed", http.StatusBadRequest)
return
}
bot, ok := s.registry.Get(slug)
if !ok {
http.Error(w, "unknown bot", http.StatusNotFound)
return
}
if !verifyTelegramSecret(r.Header.Get("X-Telegram-Bot-Api-Secret-Token"), bot.Secret) {
http.Error(w, "unauthorized", http.StatusUnauthorized)
return
}
var update Update
dec := json.NewDecoder(r.Body)
dec.DisallowUnknownFields()
if err := dec.Decode(&update); err != nil {
http.Error(w, "bad update payload", http.StatusBadRequest)
return
}
if err := bot.Handler.Handle(r.Context(), update, bot); err != nil {
log.Printf("bot=%s update=%d handler error: %v", slug, update.UpdateID, err)
}
w.WriteHeader(http.StatusOK)
_, _ = fmt.Fprint(w, "{}")
}