93 lines
2.2 KiB
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)
|
|
}
|