52 lines
1.6 KiB
Go
52 lines
1.6 KiB
Go
package rules
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
)
|
|
|
|
// AndRule combines multiple rules with AND logic
|
|
type AndRule struct {
|
|
Rules []Rule `json:"and"` // Child rules (extractors can be null/omitted)
|
|
Archivers []ArchiverConfig `json:"extractors,omitempty"` // Optional: only present on root rules, can be null for child rules (JSON tag kept for backward compatibility)
|
|
}
|
|
|
|
// Matches evaluates all child rules and returns archivers only if ALL match
|
|
func (r *AndRule) Matches(ctx context.Context, metadata *URLMetadata) ([]ArchiverConfig, error) {
|
|
if len(r.Rules) == 0 {
|
|
return nil, nil
|
|
}
|
|
|
|
// Evaluate all child rules - they should return empty slice if they match (even without archivers)
|
|
// We only care about match/no-match, not archivers from child rules
|
|
for _, childRule := range r.Rules {
|
|
archivers, err := childRule.Matches(ctx, metadata)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("error evaluating child rule: %w", err)
|
|
}
|
|
// If child rule doesn't match (returns nil), AND fails
|
|
// Empty slice means matched, nil means didn't match
|
|
if archivers == nil {
|
|
return nil, nil
|
|
}
|
|
}
|
|
|
|
// All child rules matched, return root rule's archivers
|
|
return r.Archivers, nil
|
|
}
|
|
|
|
// IsValid validates that the rule is properly defined
|
|
func (r *AndRule) IsValid() error {
|
|
if len(r.Rules) == 0 {
|
|
return fmt.Errorf("and rule: at least one child rule is required")
|
|
}
|
|
|
|
// Validate all child rules
|
|
for i, childRule := range r.Rules {
|
|
if err := childRule.IsValid(); err != nil {
|
|
return fmt.Errorf("and rule: child rule %d is invalid: %w", i, err)
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|