autobrr/internal/domain/rejections.go

168 lines
3 KiB
Go

// Copyright (c) 2021-2025, Ludvig Lundgren and the autobrr contributors.
// SPDX-License-Identifier: GPL-2.0-or-later
package domain
import (
"encoding/json"
"fmt"
"strings"
"sync"
)
type Rejection struct {
key string
got any
want any
format string
}
type RejectionReasons struct {
m sync.RWMutex
data []Rejection
}
func (r *RejectionReasons) Len() int {
return len(r.data)
}
func NewRejectionReasons() *RejectionReasons {
return &RejectionReasons{
data: make([]Rejection, 0),
}
}
func (r *RejectionReasons) String() string {
r.m.RLock()
defer r.m.RUnlock()
if len(r.data) == 0 {
return ""
}
builder := strings.Builder{}
for i, rejection := range r.data {
if i > 0 {
builder.WriteString(", ")
}
if rejection.format != "" {
fmt.Fprintf(&builder, rejection.format, rejection.key, rejection.got, rejection.want)
continue
}
fmt.Fprintf(&builder, "[%s] not matching: got %v want: %v", rejection.key, rejection.got, rejection.want)
}
return builder.String()
}
func (r *RejectionReasons) StringTruncated() string {
r.m.RLock()
defer r.m.RUnlock()
if len(r.data) == 0 {
return ""
}
builder := strings.Builder{}
for i, rejection := range r.data {
got := rejection.got
switch v := rejection.got.(type) {
case string:
if len(v) > 1024 {
got = v[:1024]
}
}
want := rejection.want
switch v := rejection.want.(type) {
case string:
if len(v) > 1024 {
want = v[:1024]
}
}
if i > 0 {
builder.WriteString(", ")
}
fmt.Fprintf(&builder, "[%s] not matching: got %v want: %v", rejection.key, got, want)
}
return builder.String()
}
func (r *RejectionReasons) WriteString() string {
r.m.RLock()
defer r.m.RUnlock()
var output []string
for _, rejection := range r.data {
output = append(output, fmt.Sprintf("[%s] not matching: got %v want: %v", rejection.key, rejection.got, rejection.want))
}
return strings.Join(output, ", ")
}
func (r *RejectionReasons) WriteJSON() ([]byte, error) {
r.m.RLock()
defer r.m.RUnlock()
var output map[string]string
for _, rejection := range r.data {
output[rejection.key] = fmt.Sprintf("[%s] not matching: got %v want: %v", rejection.key, rejection.got, rejection.want)
}
return json.Marshal(output)
}
func (r *RejectionReasons) Add(key string, got any, want any) {
r.m.Lock()
defer r.m.Unlock()
r.data = append(r.data, Rejection{
key: key,
got: got,
want: want,
})
}
func (r *RejectionReasons) Addf(key string, format string, got any, want any) {
r.m.Lock()
defer r.m.Unlock()
r.data = append(r.data, Rejection{
key: key,
format: format,
got: got,
want: want,
})
}
func (r *RejectionReasons) AddTruncated(key string, got any, want any) {
r.m.Lock()
defer r.m.Unlock()
switch wanted := want.(type) {
case string:
if len(wanted) > 1024 {
want = wanted[:1024]
}
case []string:
for i, s := range wanted {
if len(s) > 1024 {
wanted[i] = s[:1024]
}
}
}
r.Add(key, got, want)
}
// Clear rejections
func (r *RejectionReasons) Clear() {
r.m.Lock()
defer r.m.Unlock()
r.data = make([]Rejection, 0)
}