单二进制三角色 + Dock 适配器 + Swarm stack 达到可部署态;mgr1 实测订阅经 central-proxy bootstrap,探活 alive=41/52。 Co-authored-by: Cursor <cursoragent@cursor.com>
56 lines
1.8 KiB
Go
56 lines
1.8 KiB
Go
// searx_parse.go:searxng json 样本解析(RawResult.Extra → 中间条目)。
|
||
//
|
||
// 形状权威:bench/searxng-cn/samples/t1-1.excerpt.json(title/url/content/engine
|
||
// + publishedDate 可选 + unresponsive_engines)。与 dock 包的响应解码解耦:
|
||
// 模版层只认 Extra 里的 searx_results。
|
||
package scheduler
|
||
|
||
import (
|
||
"encoding/json"
|
||
"time"
|
||
|
||
"onesvm.com/onesvm/browser-server/internal/contract"
|
||
)
|
||
|
||
// searxItem 搜索条目(与 dock 侧响应形状一致;publishedDate 为引擎返回字符串)。
|
||
type searxItem struct {
|
||
Title string `json:"title"`
|
||
URL string `json:"url"`
|
||
Content string `json:"content"`
|
||
Engine string `json:"engine"`
|
||
PublishedDate *string `json:"publishedDate"`
|
||
}
|
||
|
||
// parseSearxResults 从 RawResult.Extra 解析结果条目与 unresponsive 引擎名。
|
||
func parseSearxResults(raw *contract.RawResult) ([]searxItem, []string) {
|
||
var items []searxItem
|
||
if v, ok := raw.Extra["searx_results"]; ok {
|
||
if b, err := json.Marshal(v); err == nil {
|
||
_ = json.Unmarshal(b, &items)
|
||
}
|
||
}
|
||
var unres []string
|
||
if v, ok := raw.Extra["unresponsive_engines"]; ok {
|
||
var pairs []json.RawMessage
|
||
if b, err := json.Marshal(v); err == nil && json.Unmarshal(b, &pairs) == nil {
|
||
for _, p := range pairs {
|
||
var pair [2]string
|
||
if json.Unmarshal(p, &pair) == nil && len(pair) == 2 {
|
||
unres = append(unres, pair[0]+"("+pair[1]+")")
|
||
}
|
||
}
|
||
}
|
||
}
|
||
return items, unres
|
||
}
|
||
|
||
// publishedAtOf 引擎时间串 → 东八区 Time(多格式容错;失败给 nil 由调用方置空)。
|
||
func publishedAtOf(s string) (contract.Time, bool) {
|
||
layouts := []string{time.RFC3339, "2006-01-02 15:04:05", "2006-01-02"}
|
||
for _, l := range layouts {
|
||
if t, err := time.Parse(l, s); err == nil {
|
||
return contract.NewTime(t), true
|
||
}
|
||
}
|
||
return contract.Time{}, false
|
||
}
|