//go:build experimental // +build experimental package main import ( "bytes" "encoding/binary" "fmt" "time" ) var videoResultsChan = make(chan []VideoResult) func tryOtherNodesForVideoSearch(query, safe, lang string, page int) []VideoResult { for _, node := range sockets { results, err := sendVideoSearchRequestToNode(node, query, safe, lang, page) if err != nil { printWarn("Error contacting node %s: %v", node, err) continue } if len(results) > 0 { return results } } return nil } func sendVideoSearchRequestToNode(target, query, safe, lang string, page int) ([]VideoResult, error) { payload, err := encodeSearchTextParams(query, safe, lang, page) if err != nil { return nil, fmt.Errorf("encode error: %v", err) } msg := Message{ ID: generateMessageID(), Type: MsgTypeSearchVideoRequest, Content: payload, Target: target, } if err := sendMessage(msg); err != nil { return nil, fmt.Errorf("send error: %v", err) } select { case res := <-videoResultsChan: return res, nil case <-time.After(20 * time.Second): return nil, fmt.Errorf("timeout waiting for results from node %s", target) } } func handleVideoResultsMessage(msg Message) { results, err := decodeVideoResults([]byte(msg.Content)) if err != nil { printWarn("Error decoding video results: %v", err) return } printDebug("Received video results: %+v", results) go func() { videoResultsChan <- results }() } func encodeVideoResults(results []VideoResult) ([]byte, error) { buf := new(bytes.Buffer) if err := binary.Write(buf, binary.BigEndian, uint16(len(results))); err != nil { return nil, err } for _, r := range results { if err := writeString(buf, r.Href); err != nil { return nil, err } if err := writeString(buf, r.Title); err != nil { return nil, err } if err := writeString(buf, r.Date); err != nil { return nil, err } if err := writeString(buf, r.Views); err != nil { return nil, err } if err := writeString(buf, r.Creator); err != nil { return nil, err } if err := writeString(buf, r.Publisher); err != nil { return nil, err } if err := writeString(buf, r.Image); err != nil { return nil, err } if err := writeString(buf, r.Duration); err != nil { return nil, err } } return buf.Bytes(), nil } func decodeVideoResults(data []byte) ([]VideoResult, error) { buf := bytes.NewReader(data) var count uint16 if err := binary.Read(buf, binary.BigEndian, &count); err != nil { return nil, err } results := make([]VideoResult, 0, count) for i := 0; i < int(count); i++ { href, err := readString(buf) if err != nil { return nil, err } title, err := readString(buf) if err != nil { return nil, err } date, err := readString(buf) if err != nil { return nil, err } views, err := readString(buf) if err != nil { return nil, err } creator, err := readString(buf) if err != nil { return nil, err } publisher, err := readString(buf) if err != nil { return nil, err } image, err := readString(buf) if err != nil { return nil, err } duration, err := readString(buf) if err != nil { return nil, err } results = append(results, VideoResult{ Href: href, Title: title, Date: date, Views: views, Creator: creator, Publisher: publisher, Image: image, Duration: duration, }) } return results, nil }