114 lines
2.6 KiB
Go
114 lines
2.6 KiB
Go
package main
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"net/http"
|
|
"net/url"
|
|
)
|
|
|
|
type videoMeta struct {
|
|
Title string `json:"title"`
|
|
Description string `json:"description"`
|
|
}
|
|
|
|
type ytVideosResponse struct {
|
|
Items []struct {
|
|
Snippet struct {
|
|
Title string `json:"title"`
|
|
Description string `json:"description"`
|
|
} `json:"snippet"`
|
|
} `json:"items"`
|
|
}
|
|
|
|
type searchResult struct {
|
|
VideoID string `json:"videoId"`
|
|
Title string `json:"title"`
|
|
ChannelTitle string `json:"channelTitle"`
|
|
Thumbnail string `json:"thumbnail"`
|
|
}
|
|
|
|
type ytSearchResponse struct {
|
|
Items []struct {
|
|
ID struct {
|
|
VideoID string `json:"videoId"`
|
|
} `json:"id"`
|
|
Snippet struct {
|
|
Title string `json:"title"`
|
|
ChannelTitle string `json:"channelTitle"`
|
|
Thumbnails struct {
|
|
Medium struct {
|
|
URL string `json:"url"`
|
|
} `json:"medium"`
|
|
} `json:"thumbnails"`
|
|
} `json:"snippet"`
|
|
} `json:"items"`
|
|
}
|
|
|
|
func searchVideos(query, apiKey string) ([]searchResult, error) {
|
|
q := url.Values{}
|
|
q.Set("part", "snippet")
|
|
q.Set("type", "video")
|
|
q.Set("maxResults", "12")
|
|
q.Set("q", query)
|
|
q.Set("key", apiKey)
|
|
|
|
resp, err := http.Get("https://www.googleapis.com/youtube/v3/search?" + q.Encode())
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer resp.Body.Close()
|
|
|
|
if resp.StatusCode != http.StatusOK {
|
|
return nil, fmt.Errorf("youtube search status %d", resp.StatusCode)
|
|
}
|
|
|
|
var parsed ytSearchResponse
|
|
if err := json.NewDecoder(resp.Body).Decode(&parsed); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
results := make([]searchResult, 0, len(parsed.Items))
|
|
for _, item := range parsed.Items {
|
|
if item.ID.VideoID == "" {
|
|
continue
|
|
}
|
|
results = append(results, searchResult{
|
|
VideoID: item.ID.VideoID,
|
|
Title: item.Snippet.Title,
|
|
ChannelTitle: item.Snippet.ChannelTitle,
|
|
Thumbnail: item.Snippet.Thumbnails.Medium.URL,
|
|
})
|
|
}
|
|
return results, nil
|
|
}
|
|
|
|
func fetchVideoMeta(videoID, apiKey string) (*videoMeta, error) {
|
|
q := url.Values{}
|
|
q.Set("part", "snippet")
|
|
q.Set("id", videoID)
|
|
q.Set("key", apiKey)
|
|
|
|
resp, err := http.Get("https://www.googleapis.com/youtube/v3/videos?" + q.Encode())
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer resp.Body.Close()
|
|
|
|
if resp.StatusCode != http.StatusOK {
|
|
return nil, fmt.Errorf("youtube api status %d", resp.StatusCode)
|
|
}
|
|
|
|
var parsed ytVideosResponse
|
|
if err := json.NewDecoder(resp.Body).Decode(&parsed); err != nil {
|
|
return nil, err
|
|
}
|
|
if len(parsed.Items) == 0 {
|
|
return nil, fmt.Errorf("video not found: %s", videoID)
|
|
}
|
|
|
|
return &videoMeta{
|
|
Title: parsed.Items[0].Snippet.Title,
|
|
Description: parsed.Items[0].Snippet.Description,
|
|
}, nil
|
|
}
|