feat: implement rule application engine with full-text variant support, batch entry processing, and tag visualization in UI.
This commit is contained in:
@@ -59,10 +59,19 @@ func (e *Evaluator) resolveField(field string, entry models.FeedEntry) interface
|
||||
case "url":
|
||||
return entry.URL
|
||||
case "content", "raw_content", "rss_content":
|
||||
var parts []string
|
||||
if entry.Content != "" {
|
||||
return entry.Content
|
||||
parts = append(parts, entry.Content)
|
||||
}
|
||||
return entry.RawContent
|
||||
if entry.RawContent != "" && entry.RawContent != entry.Content {
|
||||
parts = append(parts, entry.RawContent)
|
||||
}
|
||||
if entry.Variants != nil {
|
||||
if v, ok := entry.Variants["readability_full_text"]; ok && v.TextValue != "" {
|
||||
parts = append(parts, v.TextValue)
|
||||
}
|
||||
}
|
||||
return strings.Join(parts, "\n")
|
||||
case "is_read":
|
||||
return entry.IsRead
|
||||
case "is_starred":
|
||||
@@ -127,13 +136,17 @@ func (e *Evaluator) compare(actual interface{}, op string, expected interface{})
|
||||
case "neq", "!=":
|
||||
return !strings.EqualFold(actualStr, expectedStr)
|
||||
case "contains":
|
||||
return strings.Contains(strings.ToLower(actualStr), strings.ToLower(expectedStr))
|
||||
expectedClean := strings.Trim(expectedStr, "\"'` \t\r\n")
|
||||
return strings.Contains(strings.ToLower(actualStr), strings.ToLower(expectedClean))
|
||||
case "not_contains":
|
||||
return !strings.Contains(strings.ToLower(actualStr), strings.ToLower(expectedStr))
|
||||
expectedClean := strings.Trim(expectedStr, "\"'` \t\r\n")
|
||||
return !strings.Contains(strings.ToLower(actualStr), strings.ToLower(expectedClean))
|
||||
case "starts_with":
|
||||
return strings.HasPrefix(strings.ToLower(actualStr), strings.ToLower(expectedStr))
|
||||
expectedClean := strings.Trim(expectedStr, "\"'` \t\r\n")
|
||||
return strings.HasPrefix(strings.ToLower(actualStr), strings.ToLower(expectedClean))
|
||||
case "ends_with":
|
||||
return strings.HasSuffix(strings.ToLower(actualStr), strings.ToLower(expectedStr))
|
||||
expectedClean := strings.Trim(expectedStr, "\"'` \t\r\n")
|
||||
return strings.HasSuffix(strings.ToLower(actualStr), strings.ToLower(expectedClean))
|
||||
case "contains_any":
|
||||
tokens := parseStringList(expected)
|
||||
for _, token := range tokens {
|
||||
@@ -204,19 +217,31 @@ func (e *Evaluator) compareTime(t time.Time, op string, expected interface{}) bo
|
||||
|
||||
func parseStringList(val interface{}) []string {
|
||||
var result []string
|
||||
clean := func(s string) string {
|
||||
s = strings.TrimSpace(s)
|
||||
s = strings.Trim(s, "\"'`")
|
||||
return strings.TrimSpace(s)
|
||||
}
|
||||
|
||||
switch v := val.(type) {
|
||||
case []interface{}:
|
||||
for _, item := range v {
|
||||
result = append(result, strings.TrimSpace(fmt.Sprintf("%v", item)))
|
||||
itemStr := clean(fmt.Sprintf("%v", item))
|
||||
if itemStr != "" {
|
||||
result = append(result, itemStr)
|
||||
}
|
||||
}
|
||||
case []string:
|
||||
for _, item := range v {
|
||||
result = append(result, strings.TrimSpace(item))
|
||||
itemStr := clean(item)
|
||||
if itemStr != "" {
|
||||
result = append(result, itemStr)
|
||||
}
|
||||
}
|
||||
case string:
|
||||
parts := strings.Split(v, ",")
|
||||
for _, part := range parts {
|
||||
trimmed := strings.TrimSpace(part)
|
||||
trimmed := clean(part)
|
||||
if trimmed != "" {
|
||||
result = append(result, trimmed)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user