GoGronkh/youtube/youtube.go

222 lines
5.1 KiB
Go

package youtube
import (
"encoding/json"
"net/http"
"net/url"
"io/ioutil"
"strings"
"errors"
"log"
"fmt"
)
type Thumb struct {
Url string
Width int
Height int
}
type Snip struct {
PublishedAt string
Title string
Description string
Thumbnails map[string]Thumb
}
type ContentD struct {
Duration string
}
type Stats struct {
LikeCount int64 `json:",string"`
DislikeCount int64 `json:",string"`
}
type Stat struct {
UploadStatus string
PrivacyStatus string
}
type BrandingSetting struct {
Image map[string]string
}
type Error struct {
Code int
Message string
}
type Item struct {
Id string
Snippet Snip
ContentDetails ContentD
Status Stat
Statistics Stats
BrandingSettings BrandingSetting
}
type YTResult struct {
Items []Item
Error *Error
}
var videoEndpoint string = "https://www.googleapis.com/youtube/v3/videos"
var channelEndpoint string = "https://www.googleapis.com/youtube/v3/channels"
var sem = make(chan byte, 5)
var client = &http.Client {}
// Make an HTTP Get Request to u
func GetHTTPResource(u string) (*http.Response, error) {
sem <- 1
// Prepare HTTP Client, Cookie and Request
req, err := http.NewRequest("GET", u, nil)
if err != nil {
log.Fatalf("FAT HTTP - Failed to create new Request: %+v", err)
<- sem
return nil, err
}
// Execute HTTP Request
res, err := client.Do(req)
if err != nil {
<- sem
return nil, err
}
if res.StatusCode == 404 {
res.Body.Close()
<- sem
return nil, nil
}
<- sem
return res, nil
}
func GetVideos(parts []string, ids []string, key string) (*YTResult, error) {
var ytVideo YTResult
u, _ := url.Parse(videoEndpoint)
query := u.Query()
// Stringify arraysfmt
p := strings.Join(parts, ",")
i := strings.Join(ids, ",")
// Set params in URL Query
query.Set("part", p)
query.Set("id", i)
query.Set("key", key)
u.RawQuery = query.Encode()
res, err := GetHTTPResource(u.String())
if err != nil {
return nil, err
}
defer res.Body.Close()
body, err := ioutil.ReadAll(res.Body)
if err != nil {
return nil, err
}
jerr := json.Unmarshal(body, &ytVideo)
if jerr != nil {
return nil, jerr
}
return &ytVideo, nil
}
func GetChannel(parts []string, id string, key string) (*YTResult, error) {
var ytRes YTResult
u, _ := url.Parse(channelEndpoint)
query := u.Query()
// Stringify array
p := strings.Join(parts, ",")
// Set params in URL Query
query.Set("part", p)
query.Set("id", id)
query.Set("key", key)
u.RawQuery = query.Encode()
res, err := GetHTTPResource(u.String())
if err != nil {
return nil, err
}
defer res.Body.Close()
body, err := ioutil.ReadAll(res.Body)
if err != nil {
return nil, err
}
jerr := json.Unmarshal(body, &ytRes)
if jerr != nil {
return nil, jerr
}
if ytRes.Error != nil {
return nil, fmt.Errorf("Youtube Error: %+v: %s", ytRes.Error.Code, ytRes.Error.Message)
}
return &ytRes, nil
}
func GetChannelId(name string, key string) (string, error) {
var ytRes YTResult
u, _ := url.Parse(channelEndpoint)
query := u.Query()
// Set params in URL Query
query.Set("part", "snippet")
query.Set("forUsername", name)
query.Set("key", key)
u.RawQuery = query.Encode()
res, err := GetHTTPResource(u.String())
if err != nil {
return "", err
}
defer res.Body.Close()
body, err := ioutil.ReadAll(res.Body)
if err != nil {
return "", err
}
jerr := json.Unmarshal(body, &ytRes)
if jerr != nil {
return "", jerr
}
if len(ytRes.Items) < 0 {
return "", errors.New("API Error")
}
return ytRes.Items[0].Id, nil
}
func GetRatingAndVotesWithId(id string, key string) (float64, int64, string, Thumb) {
ytres, err := GetVideos([]string {"statistics", "status", "snippet"}, []string {id}, key)
if err != nil || len(ytres.Items) == 0 {
return 0, 0, "private", Thumb{}
}
votes := ytres.Items[0].Statistics.LikeCount + ytres.Items[0].Statistics.DislikeCount
var rating float64
if ytres.Items[0].Statistics.LikeCount != 0 {
rating = (float64(ytres.Items[0].Statistics.LikeCount)/float64(votes))*10
} else {
rating = 0
}
status := ytres.Items[0].Status.PrivacyStatus
if ytres.Items[0].Status.UploadStatus != "processed" {
status = "private"
}
thumb, ok := ytres.Items[0].Snippet.Thumbnails["maxres"]
if !ok {
thumb, ok = ytres.Items[0].Snippet.Thumbnails["high"]
}
return rating, votes, status, thumb
}
func GetRatingAndVotesWithRes(ytres *YTResult) (float64, int64) {
votes := ytres.Items[0].Statistics.LikeCount + ytres.Items[0].Statistics.DislikeCount
var rating float64
if ytres.Items[0].Statistics.LikeCount != 0 {
rating = (float64(ytres.Items[0].Statistics.LikeCount)/float64(votes))*10
} else {
rating = 0
}
return rating, votes
}