aibow/youtube.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
}