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/main.go

149 lines
3.4 KiB
Go

package main
import (
"context"
"fmt"
"log"
"net/http"
"os"
"os/signal"
"syscall"
"time"
"gitea.dwysokinski.me/Kichiyaki/notificationarr/internal/rest"
"gitea.dwysokinski.me/Kichiyaki/notificationarr/internal/service"
"github.com/go-chi/chi/v5"
"github.com/go-chi/chi/v5/middleware"
)
const (
defaultPort = "9234"
readTimeout = 2 * time.Second
readHeaderTimeout = 2 * time.Second
writeTimeout = 2 * time.Second
idleTimeout = 2 * time.Second
serverShutdownTimeout = 10 * time.Second
ntfyDefaultUrl = "https://ntfy.sh"
publisherDefaultTimeout = 5 * time.Second
)
func main() {
srv, err := newServer()
if err != nil {
log.Fatalln("newServer:", err)
}
go startServer(srv)
log.Println("Server is listening on the port", defaultPort)
waitForSignal(context.Background())
ctxShutdown, cancelShutdown := context.WithTimeout(context.Background(), serverShutdownTimeout)
defer cancelShutdown()
err = srv.Shutdown(ctxShutdown)
if err != nil {
log.Println("srv.Shutdown:", err)
}
}
func newServer() (*http.Server, error) {
router, err := newRouter()
if err != nil {
return nil, fmt.Errorf("newRouter: %w", err)
}
return &http.Server{
Addr: ":" + defaultPort,
Handler: router,
ReadTimeout: readTimeout,
ReadHeaderTimeout: readHeaderTimeout,
WriteTimeout: writeTimeout,
IdleTimeout: idleTimeout,
}, nil
}
func newRouter() (*chi.Mux, error) {
sonarrSvc, err := newSonarrService()
if err != nil {
return nil, fmt.Errorf("newSonarrService: %w", err)
}
radarrSvc, err := newRadarrService()
if err != nil {
return nil, fmt.Errorf("newRadarrService: %w", err)
}
r := chi.NewRouter()
r.Use(
middleware.RealIP,
middleware.RequestLogger(&middleware.DefaultLogFormatter{
NoColor: true,
Logger: log.Default(),
}),
middleware.Recoverer,
middleware.Heartbeat("/health"),
)
rest.NewWebhookHandler(sonarrSvc, radarrSvc).Register(r)
return r, nil
}
func newRadarrService() (*service.Radarr, error) {
ntfy, err := newNtfyService("RADARR")
if err != nil {
return nil, fmt.Errorf("newNtfyService: %w", err)
}
return service.NewRadarr(ntfy), nil
}
func newSonarrService() (*service.Sonarr, error) {
ntfy, err := newNtfyService("SONARR")
if err != nil {
return nil, fmt.Errorf("newNtfyService: %w", err)
}
return service.NewSonarr(ntfy), nil
}
func newNtfyService(envPrefix string) (*service.Ntfy, error) {
url := os.Getenv(envPrefix + "_NTFY_URL")
if url == "" {
url = ntfyDefaultUrl
}
topic := os.Getenv(envPrefix + "_NTFY_TOPIC")
if topic == "" {
return nil, fmt.Errorf(`env "%s_NTFY_TOPIC" is required`, envPrefix)
}
timeout := os.Getenv(envPrefix + "_NTFY_REQ_TIMEOUT")
parsedTimeout := publisherDefaultTimeout
var err error
if timeout != "" {
parsedTimeout, err = time.ParseDuration(timeout)
}
if err != nil {
return nil, fmt.Errorf(`os.Getenv("%s_NTFY_REQ_TIMEOUT"): %w`, envPrefix, err)
}
return service.NewNtfy(
&http.Client{Timeout: parsedTimeout},
url,
topic,
os.Getenv(envPrefix+"_NTFY_USERNAME"),
os.Getenv(envPrefix+"_NTFY_PASSWORD"),
), nil
}
func startServer(srv *http.Server) {
if err := srv.ListenAndServe(); err != nil && err != http.ErrServerClosed {
log.Fatalln("srv.ListenAndServe:", err)
}
}
func waitForSignal(ctx context.Context) {
ctx, stop := signal.NotifyContext(ctx, os.Interrupt, syscall.SIGTERM)
defer stop()
<-ctx.Done()
}