This repository has been archived on 2023-04-18. You can view files and clone it, but cannot push or open issues or pull requests.
notificationarr/internal/rest/webhook_handler.go

93 lines
2.2 KiB
Go

package rest
import (
"context"
"encoding/json"
"fmt"
"net/http"
"gitea.dwysokinski.me/Kichiyaki/notificationarr/internal/domain"
"github.com/go-chi/chi/v5"
)
//counterfeiter:generate -o internal/mock/sonarr_service.gen.go . SonarrService
type SonarrService interface {
Process(ctx context.Context, payload domain.SonarrWebhookPayload) error
}
type WebhookHandler struct {
sonarrSvc SonarrService
}
func NewWebhookHandler(sonarrSvc SonarrService) *WebhookHandler {
return &WebhookHandler{
sonarrSvc: sonarrSvc,
}
}
func (h *WebhookHandler) Register(r chi.Router) {
r.Post("/webhook/sonarr", h.handleSonarrWebhook)
}
type SonarrSeries struct {
ID int64 `json:"id"`
Title string `json:"title"`
}
type SonarrEpisode struct {
ID int64 `json:"id"`
EpisodeNumber int16 `json:"episodeNumber"`
SeasonNumber int16 `json:"seasonNumber"`
Title string `json:"title"`
}
type SonarrWebhookRequest struct {
EventType string `json:"eventType"`
Series SonarrSeries `json:"series"`
Episodes []SonarrEpisode `json:"episodes"`
}
func (h *WebhookHandler) handleSonarrWebhook(w http.ResponseWriter, r *http.Request) {
var req SonarrWebhookRequest
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
renderErrorResponse(w, domain.NewError(
domain.WithErr(err),
domain.WithCode(domain.ErrorCodeValidation),
domain.WithMessage("invalid request body"),
))
return
}
eventType, err := domain.NewSonarrEventType(req.EventType)
if err != nil {
renderErrorResponse(w, fmt.Errorf("domain.NewSonarrEventType: %w", err))
return
}
payload := domain.SonarrWebhookPayload{
EventType: eventType,
Series: domain.SonarrSeries{
ID: req.Series.ID,
Title: req.Series.Title,
},
Episodes: make([]domain.SonarrEpisode, 0, len(req.Episodes)),
}
for _, ep := range req.Episodes {
payload.Episodes = append(payload.Episodes, domain.SonarrEpisode{
ID: ep.ID,
EpisodeNumber: ep.EpisodeNumber,
SeasonNumber: ep.SeasonNumber,
Title: ep.Title,
})
}
if err := h.sonarrSvc.Process(r.Context(), payload); err != nil {
renderErrorResponse(w, fmt.Errorf("SonarrService.Process: %w", err))
return
}
w.WriteHeader(http.StatusNoContent)
}