86 lines
2.1 KiB
Go
86 lines
2.1 KiB
Go
|
package main
|
||
|
|
||
|
import (
|
||
|
"encoding/json"
|
||
|
"fmt"
|
||
|
"net/http"
|
||
|
"net/url"
|
||
|
)
|
||
|
|
||
|
type MusicAPIResponse struct {
|
||
|
Items []struct {
|
||
|
Title string `json:"title"`
|
||
|
UploaderName string `json:"uploaderName"`
|
||
|
Duration int `json:"duration"`
|
||
|
Thumbnail string `json:"thumbnail"`
|
||
|
URL string `json:"url"`
|
||
|
} `json:"items"` // Removed VideoID since we'll parse from URL
|
||
|
}
|
||
|
|
||
|
func SearchMusicViaPiped(query string, page int) ([]MusicResult, error) {
|
||
|
var lastError error
|
||
|
mu.Lock()
|
||
|
defer mu.Unlock()
|
||
|
|
||
|
for _, instance := range pipedInstances {
|
||
|
if disabledInstances[instance] {
|
||
|
continue
|
||
|
}
|
||
|
|
||
|
url := fmt.Sprintf(
|
||
|
"https://%s/search?q=%s&filter=music_songs&page=%d",
|
||
|
instance,
|
||
|
url.QueryEscape(query),
|
||
|
page,
|
||
|
)
|
||
|
|
||
|
resp, err := http.Get(url)
|
||
|
if err != nil || resp.StatusCode != http.StatusOK {
|
||
|
printInfo("Disabling instance %s due to error: %v", instance, err)
|
||
|
disabledInstances[instance] = true
|
||
|
lastError = fmt.Errorf("request to %s failed: %w", instance, err)
|
||
|
continue
|
||
|
}
|
||
|
|
||
|
defer resp.Body.Close()
|
||
|
var apiResp MusicAPIResponse
|
||
|
if err := json.NewDecoder(resp.Body).Decode(&apiResp); err != nil {
|
||
|
lastError = fmt.Errorf("failed to decode response from %s: %w", instance, err)
|
||
|
continue
|
||
|
}
|
||
|
|
||
|
return convertPipedToMusicResults(instance, apiResp), nil
|
||
|
}
|
||
|
|
||
|
return nil, fmt.Errorf("all Piped instances failed, last error: %v", lastError)
|
||
|
}
|
||
|
|
||
|
func convertPipedToMusicResults(instance string, resp MusicAPIResponse) []MusicResult {
|
||
|
seen := make(map[string]bool)
|
||
|
var results []MusicResult
|
||
|
|
||
|
for _, item := range resp.Items {
|
||
|
// Extract video ID from URL
|
||
|
u, err := url.Parse(item.URL)
|
||
|
if err != nil {
|
||
|
continue
|
||
|
}
|
||
|
videoID := u.Query().Get("v")
|
||
|
if videoID == "" || seen[videoID] {
|
||
|
continue
|
||
|
}
|
||
|
seen[videoID] = true
|
||
|
|
||
|
results = append(results, MusicResult{
|
||
|
Title: item.Title,
|
||
|
Artist: item.UploaderName,
|
||
|
URL: fmt.Sprintf("https://music.youtube.com%s", item.URL),
|
||
|
Duration: formatDuration(item.Duration),
|
||
|
Thumbnail: item.Thumbnail,
|
||
|
Source: "YouTube Music",
|
||
|
//AudioURL: fmt.Sprintf("https://%s/stream/%s", instance, videoID),
|
||
|
})
|
||
|
}
|
||
|
return results
|
||
|
}
|