diff --git a/node-handle-search.go b/node-handle-search.go index 3992de0..77819be 100644 --- a/node-handle-search.go +++ b/node-handle-search.go @@ -99,10 +99,11 @@ func handleSearchImageMessage(msg Message) { func handleSearchVideoMessage(msg Message) { var searchParams struct { - Query string `json:"query"` - Safe string `json:"safe"` - Lang string `json:"lang"` - Page int `json:"page"` + Query string `json:"query"` + Safe string `json:"safe"` + Lang string `json:"lang"` + Page int `json:"page"` + ResponseAddr string `json:"responseAddr"` } err := json.Unmarshal([]byte(msg.Content), &searchParams) if err != nil { @@ -110,6 +111,8 @@ func handleSearchVideoMessage(msg Message) { return } + log.Printf("Received search-video request. ResponseAddr: %s", searchParams.ResponseAddr) + results := fetchVideoResults(searchParams.Query, searchParams.Safe, searchParams.Lang, searchParams.Page) resultsJSON, err := json.Marshal(results) if err != nil { @@ -123,9 +126,16 @@ func handleSearchVideoMessage(msg Message) { Content: string(resultsJSON), } - err = sendMessage(msg.ID, responseMsg) + log.Printf("Sending video search results to %s", searchParams.ResponseAddr) + + if searchParams.ResponseAddr == "" { + log.Printf("Error: Response address is empty") + return + } + + err = sendMessage(searchParams.ResponseAddr, responseMsg) if err != nil { - log.Printf("Error sending video search results to %s: %v", msg.ID, err) + log.Printf("Error sending video search results to %s: %v", searchParams.ResponseAddr, err) } } diff --git a/node.go b/node.go index 824577f..56ffd82 100644 --- a/node.go +++ b/node.go @@ -157,10 +157,10 @@ func interpretMessage(msg Message) { handleTextResultsMessage(msg) // need to implement case "image-results": handleImageResultsMessage(msg) // need to implement - // case "video-results": - // handleVideoResultsMessage(msg) // need to implement - // case "file-results": - // handleFileResultsMessage(msg) // need to implement + case "video-results": + handleVideoResultsMessage(msg) // need to implement + case "file-results": + handleFileResultsMessage(msg) // need to implement default: fmt.Println("Received unknown message type:", msg.Type) } diff --git a/video.go b/video.go index 36d0613..697f3c7 100644 --- a/video.go +++ b/video.go @@ -30,6 +30,7 @@ var ( } disabledInstances = make(map[string]bool) mu sync.Mutex + videoResultsChan = make(chan []VideoResult) // Channel to receive video results from other nodes ) // VideoAPIResponse matches the structure of the JSON response from the Piped API @@ -151,32 +152,10 @@ func makeHTMLRequest(query, safe, lang string, page int) (*VideoAPIResponse, err func handleVideoSearch(w http.ResponseWriter, query, safe, lang string, page int) { start := time.Now() - apiResp, err := makeHTMLRequest(query, safe, lang, page) - if err != nil { - log.Printf("Error fetching video results: %v", err) - http.Error(w, "Internal Server Error", http.StatusInternalServerError) - return - } - - var results []VideoResult - for _, item := range apiResp.Items { - if item.Type == "channel" || item.Type == "playlist" { - continue - } - if item.UploadedDate == "" { - item.UploadedDate = "Now" - } - - results = append(results, VideoResult{ - Href: fmt.Sprintf("https://youtube.com%s", item.URL), - Title: item.Title, - Date: item.UploadedDate, - Views: formatViews(item.Views), - Creator: item.UploaderName, - Publisher: "Piped", - Image: fmt.Sprintf("/img_proxy?url=%s", url.QueryEscape(item.Thumbnail)), - Duration: formatDuration(item.Duration), - }) + results := fetchVideoResults(query, safe, lang, page) + if len(results) == 0 { + log.Printf("No results from primary search, trying other nodes") + results = tryOtherNodesForVideoSearch(query, safe, lang, page) } elapsed := time.Since(start) @@ -230,3 +209,72 @@ func fetchVideoResults(query, safe, lang string, page int) []VideoResult { } return results } + +func tryOtherNodesForVideoSearch(query, safe, lang string, page int) []VideoResult { + for _, nodeAddr := range peers { + results, err := sendVideoSearchRequestToNode(nodeAddr, query, safe, lang, page) + if err != nil { + log.Printf("Error contacting node %s: %v", nodeAddr, err) + continue + } + if len(results) > 0 { + return results + } + } + return nil +} + +func sendVideoSearchRequestToNode(nodeAddr, query, safe, lang string, page int) ([]VideoResult, error) { + searchParams := struct { + Query string `json:"query"` + Safe string `json:"safe"` + Lang string `json:"lang"` + Page int `json:"page"` + ResponseAddr string `json:"responseAddr"` + }{ + Query: query, + Safe: safe, + Lang: lang, + Page: page, + ResponseAddr: fmt.Sprintf("http://localhost:%d/node", config.Port), + } + + msgBytes, err := json.Marshal(searchParams) + if err != nil { + return nil, fmt.Errorf("failed to marshal search parameters: %v", err) + } + + msg := Message{ + ID: hostID, + Type: "search-video", + Content: string(msgBytes), + } + + err = sendMessage(nodeAddr, msg) + if err != nil { + return nil, fmt.Errorf("failed to send search request to node %s: %v", nodeAddr, err) + } + + // Wait for results + select { + case res := <-videoResultsChan: + return res, nil + case <-time.After(20 * time.Second): + return nil, fmt.Errorf("timeout waiting for results from node %s", nodeAddr) + } +} + +func handleVideoResultsMessage(msg Message) { + var results []VideoResult + err := json.Unmarshal([]byte(msg.Content), &results) + if err != nil { + log.Printf("Error unmarshalling video results: %v", err) + return + } + + log.Printf("Received video results: %+v", results) + // Send results to videoResultsChan + go func() { + videoResultsChan <- results + }() +}