//go:build experimental // +build experimental package main import ( "bytes" "encoding/binary" "fmt" "time" ) var musicResultsChan = make(chan []MusicResult) func tryOtherNodesForMusicSearch(query, lang string, safe bool, page int) []MusicResult { safeStr := "inactive" if safe { safeStr = "active" } for _, nodeTarget := range sockets { results, err := sendMusicSearchRequestToNode(nodeTarget, query, safeStr, lang, page) if err != nil { printWarn("Error contacting node %s: %v", nodeTarget, err) continue } if len(results) > 0 { return results } } return nil } func sendMusicSearchRequestToNode(target, query, safe, lang string, page int) ([]MusicResult, error) { payload, err := encodeSearchTextParams(query, safe, lang, page) if err != nil { return nil, fmt.Errorf("encode error: %v", err) } msg := Message{ ID: generateMessageID(), Type: MsgTypeSearchMusicRequest, Content: payload, Target: target, } err = sendMessage(msg) if err != nil { return nil, fmt.Errorf("failed to send music request to node %s: %v", target, err) } select { case res := <-musicResultsChan: return res, nil case <-time.After(20 * time.Second): return nil, fmt.Errorf("timeout waiting for music results from node %s", target) } } func handleMusicResultsMessage(msg Message) { results, err := decodeMusicResults([]byte(msg.Content)) if err != nil { printWarn("Error decoding music results: %v", err) return } printDebug("Received music results: %+v", results) go func() { musicResultsChan <- results }() } func encodeMusicResults(results []MusicResult) ([]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.URL); err != nil { return nil, err } if err := writeString(buf, r.Title); err != nil { return nil, err } if err := writeString(buf, r.Artist); err != nil { return nil, err } if err := writeString(buf, r.Description); err != nil { return nil, err } if err := writeString(buf, r.PublishedDate); err != nil { return nil, err } if err := writeString(buf, r.Thumbnail); err != nil { return nil, err } if err := writeString(buf, r.Source); err != nil { return nil, err } if err := writeString(buf, r.Duration); err != nil { return nil, err } } return buf.Bytes(), nil } func decodeMusicResults(data []byte) ([]MusicResult, error) { buf := bytes.NewReader(data) var count uint16 if err := binary.Read(buf, binary.BigEndian, &count); err != nil { return nil, err } results := make([]MusicResult, 0, count) for i := 0; i < int(count); i++ { url, err := readString(buf) if err != nil { return nil, err } title, err := readString(buf) if err != nil { return nil, err } artist, err := readString(buf) if err != nil { return nil, err } description, err := readString(buf) if err != nil { return nil, err } date, err := readString(buf) if err != nil { return nil, err } thumb, err := readString(buf) if err != nil { return nil, err } source, err := readString(buf) if err != nil { return nil, err } duration, err := readString(buf) if err != nil { return nil, err } results = append(results, MusicResult{ URL: url, Title: title, Artist: artist, Description: description, PublishedDate: date, Thumbnail: thumb, Source: source, Duration: duration, }) } return results, nil } // func handleMusicSearchRequest(msg Message) { // buf := bytes.NewReader([]byte(msg.Content)) // query, _ := readString(buf) // var page uint16 // binary.Read(buf, binary.BigEndian, &page) // results := fetchMusicResults(query, int(page)) // encoded, err := encodeMusicResults(results) // if err != nil { // printWarn("Encoding music results failed: %v", err) // return // } // reply := Message{ // ID: msg.ID, // Type: MsgTypeSearchMusicResponse, // Content: string(encoded), // Target: msg.Target, // Send back to sender // } // sendMessage(reply) // }