Files
decypharr/pkg/sabnzbd/context.go
2025-08-01 15:27:24 +01:00

122 lines
3.2 KiB
Go

package sabnzbd
import (
"context"
"github.com/sirrobot01/decypharr/internal/utils"
"github.com/sirrobot01/decypharr/pkg/store"
"net/http"
"strings"
"github.com/sirrobot01/decypharr/pkg/arr"
)
type contextKey string
const (
apiKeyKey contextKey = "apikey"
modeKey contextKey = "mode"
arrKey contextKey = "arr"
categoryKey contextKey = "category"
)
func getMode(ctx context.Context) string {
if mode, ok := ctx.Value(modeKey).(string); ok {
return mode
}
return ""
}
func (s *SABnzbd) categoryContext(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
category := r.URL.Query().Get("category")
if category == "" {
// Check form data
_ = r.ParseForm()
category = r.Form.Get("category")
}
if category == "" {
category = r.FormValue("category")
}
ctx := context.WithValue(r.Context(), categoryKey, strings.TrimSpace(category))
next.ServeHTTP(w, r.WithContext(ctx))
})
}
func getArrFromContext(ctx context.Context) *arr.Arr {
if a, ok := ctx.Value(arrKey).(*arr.Arr); ok {
return a
}
return nil
}
func getCategory(ctx context.Context) string {
if category, ok := ctx.Value(categoryKey).(string); ok {
return category
}
return ""
}
// modeContext extracts the mode parameter from the request
func (s *SABnzbd) modeContext(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
mode := r.URL.Query().Get("mode")
if mode == "" {
// Check form data
_ = r.ParseForm()
mode = r.Form.Get("mode")
}
// Extract category for Arr integration
category := r.URL.Query().Get("cat")
if category == "" {
category = r.Form.Get("cat")
}
// Create a default Arr instance for the category
downloadUncached := false
a := arr.New(category, "", "", false, false, &downloadUncached, "", "auto")
ctx := context.WithValue(r.Context(), modeKey, strings.TrimSpace(mode))
ctx = context.WithValue(ctx, arrKey, a)
next.ServeHTTP(w, r.WithContext(ctx))
})
}
// authContext creates a middleware that extracts the Arr host and token from the Authorization header
// and adds it to the request context.
// This is used to identify the Arr instance for the request.
// Only a valid host and token will be added to the context/config. The rest are manual
func (s *SABnzbd) authContext(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
host := r.FormValue("ma_username")
token := r.FormValue("ma_password")
category := getCategory(r.Context())
arrs := store.Get().Arr()
// Check if arr exists
a := arrs.Get(category)
if a == nil {
// Arr is not configured, create a new one
downloadUncached := false
a = arr.New(category, "", "", false, false, &downloadUncached, "", "auto")
}
host = strings.TrimSpace(host)
if host != "" {
a.Host = host
}
token = strings.TrimSpace(token)
if token != "" {
a.Token = token
}
a.Source = "auto"
if err := utils.ValidateServiceURL(a.Host); err != nil {
// Return silently, no need to raise a problem. Just do not add the Arr to the context/config.json
next.ServeHTTP(w, r)
return
}
arrs.AddOrUpdate(a)
ctx := context.WithValue(r.Context(), arrKey, a)
next.ServeHTTP(w, r.WithContext(ctx))
})
}