141 lines
3.7 KiB
Go
141 lines
3.7 KiB
Go
package viral
|
||
|
||
import (
|
||
"encoding/json"
|
||
"strings"
|
||
)
|
||
|
||
func firstJSONString(obj map[string]json.RawMessage, keys ...string) string {
|
||
for _, key := range keys {
|
||
raw, ok := obj[key]
|
||
if !ok {
|
||
continue
|
||
}
|
||
var value string
|
||
if err := json.Unmarshal(raw, &value); err == nil {
|
||
if trimmed := strings.TrimSpace(value); trimmed != "" {
|
||
return trimmed
|
||
}
|
||
}
|
||
}
|
||
return ""
|
||
}
|
||
|
||
func flexibleStringFromItem(raw json.RawMessage) string {
|
||
if len(raw) == 0 {
|
||
return ""
|
||
}
|
||
var value string
|
||
if err := json.Unmarshal(raw, &value); err == nil {
|
||
return strings.TrimSpace(value)
|
||
}
|
||
var obj map[string]json.RawMessage
|
||
if err := json.Unmarshal(raw, &obj); err != nil {
|
||
return ""
|
||
}
|
||
if line := firstJSONString(obj, "title", "name", "label", "pillar", "tag", "text", "summary", "description", "value", "content"); line != "" {
|
||
return line
|
||
}
|
||
parts := []string{}
|
||
for _, key := range []string{"title", "name", "label"} {
|
||
if part := firstJSONString(obj, key); part != "" {
|
||
parts = append(parts, part)
|
||
break
|
||
}
|
||
}
|
||
if detail := firstJSONString(obj, "description", "summary", "detail", "reason"); detail != "" {
|
||
parts = append(parts, detail)
|
||
}
|
||
return strings.TrimSpace(strings.Join(parts, ":"))
|
||
}
|
||
|
||
func parseFlexibleStringList(raw json.RawMessage) []string {
|
||
if len(raw) == 0 || string(raw) == "null" {
|
||
return nil
|
||
}
|
||
var items []string
|
||
if err := json.Unmarshal(raw, &items); err == nil {
|
||
return cleanLines(items)
|
||
}
|
||
var single string
|
||
if err := json.Unmarshal(raw, &single); err == nil && strings.TrimSpace(single) != "" {
|
||
return cleanLines([]string{single})
|
||
}
|
||
var arr []json.RawMessage
|
||
if err := json.Unmarshal(raw, &arr); err != nil {
|
||
return nil
|
||
}
|
||
out := make([]string, 0, len(arr))
|
||
for _, item := range arr {
|
||
if line := flexibleStringFromItem(item); line != "" {
|
||
out = append(out, line)
|
||
}
|
||
}
|
||
return cleanLines(out)
|
||
}
|
||
|
||
func parseFlexibleSuggestedTags(raw json.RawMessage) []SuggestedTag {
|
||
if len(raw) == 0 || string(raw) == "null" {
|
||
return nil
|
||
}
|
||
var tags []SuggestedTag
|
||
if err := json.Unmarshal(raw, &tags); err == nil && len(tags) > 0 {
|
||
return cleanSuggestedTags(tags)
|
||
}
|
||
var strs []string
|
||
if err := json.Unmarshal(raw, &strs); err == nil {
|
||
out := make([]SuggestedTag, 0, len(strs))
|
||
for _, item := range strs {
|
||
item = strings.TrimSpace(item)
|
||
if item != "" {
|
||
out = append(out, SuggestedTag{Tag: item})
|
||
}
|
||
}
|
||
return cleanSuggestedTags(out)
|
||
}
|
||
var arr []json.RawMessage
|
||
if err := json.Unmarshal(raw, &arr); err != nil {
|
||
return nil
|
||
}
|
||
out := make([]SuggestedTag, 0, len(arr))
|
||
for _, item := range arr {
|
||
if tag := decodeSuggestedTagItem(item); tag.Tag != "" {
|
||
out = append(out, tag)
|
||
}
|
||
}
|
||
return cleanSuggestedTags(out)
|
||
}
|
||
|
||
func decodeSuggestedTagItem(raw json.RawMessage) SuggestedTag {
|
||
var tag SuggestedTag
|
||
if err := json.Unmarshal(raw, &tag); err == nil && strings.TrimSpace(tag.Tag) != "" {
|
||
return tag
|
||
}
|
||
var snake struct {
|
||
Tag string `json:"tag"`
|
||
Reason string `json:"reason"`
|
||
SearchIntent string `json:"search_intent"`
|
||
SearchType string `json:"search_type"`
|
||
}
|
||
if err := json.Unmarshal(raw, &snake); err == nil && strings.TrimSpace(snake.Tag) != "" {
|
||
return SuggestedTag{
|
||
Tag: strings.TrimSpace(snake.Tag),
|
||
Reason: strings.TrimSpace(snake.Reason),
|
||
SearchIntent: strings.TrimSpace(snake.SearchIntent),
|
||
SearchType: strings.TrimSpace(snake.SearchType),
|
||
}
|
||
}
|
||
if line := flexibleStringFromItem(raw); line != "" {
|
||
return SuggestedTag{Tag: line}
|
||
}
|
||
return SuggestedTag{}
|
||
}
|
||
|
||
func pickRawMessage(root map[string]json.RawMessage, keys ...string) json.RawMessage {
|
||
for _, key := range keys {
|
||
if raw, ok := root[key]; ok && len(raw) > 0 && string(raw) != "null" {
|
||
return raw
|
||
}
|
||
}
|
||
return nil
|
||
} |