Issues (115)

bot/youtube.go (8 issues)

Severity
1
package bot
2
3
import (
4
	"bytes"
5
	"encoding/json"
6
	"net/http"
7
	"net/url"
8
	"os/exec"
9
	"strings"
10
)
11
12
const (
13
	// ERROR_TYPE returns if error
14
	ERROR_TYPE = -1
0 ignored issues
show
don't use ALL_CAPS in Go names; use CamelCase
Loading history...
15
	// VIDEO_TYPE returns if video
16
	VIDEO_TYPE = 0
0 ignored issues
show
don't use ALL_CAPS in Go names; use CamelCase
Loading history...
17
	// PLAYLIST_TYPE returns if playlist
18
	PLAYLIST_TYPE = 1
0 ignored issues
show
don't use ALL_CAPS in Go names; use CamelCase
Loading history...
19
)
20
21
type (
22
	videoResponse struct {
23
		Formats []struct {
24
			Url string `json:"url"`
0 ignored issues
show
struct field Url should be URL
Loading history...
25
		} `json:"formats"`
26
		Title string `json:"title"`
27
	}
28
29
	// VideoResult contains information about video
30
	VideoResult struct {
31
		Media string
32
		Title string
33
	}
34
35
	// PlaylistVideo contains playlist ID
36
	PlaylistVideo struct {
37
		Id string `json:"id"`
0 ignored issues
show
struct field Id should be ID
Loading history...
38
	}
39
40
	// YTSearchContent contains Youtube search result
41
	YTSearchContent struct {
42
		Id           string `json:"id"`
0 ignored issues
show
struct field Id should be ID
Loading history...
43
		Title        string `json:"title"`
44
		Description  string `json:"description"`
45
		ChannelTitle string `json:"channel_title"`
46
		Duration     string `json:"duration"`
47
	}
48
49
	ytApiResponse struct {
0 ignored issues
show
type ytApiResponse should be ytAPIResponse
Loading history...
50
		Error   bool              `json:"error"`
51
		Content []YTSearchContent `json:"content"`
52
	}
53
54
	// Youtube contains pointer to bot configuration struct
55
	Youtube struct {
56
		Conf *Config
57
	}
58
)
59
60
func (youtube Youtube) getType(input string) int {
61
	if strings.Contains(input, "upload_date") {
62
		return VIDEO_TYPE
63
	}
64
	if strings.Contains(input, "_type") {
65
		return PLAYLIST_TYPE
66
	}
67
	return ERROR_TYPE
68
}
69
70
// Get returns data grabbed from youtube
71
func (youtube Youtube) Get(link string) (int, *string, error) {
72
	cmd := exec.Command("./youtube-dl", "--skip-download", "--print-json", "--flat-playlist", link)
73
	var out bytes.Buffer
74
	cmd.Stdout = &out
75
	err := cmd.Run()
76
	if err != nil {
77
		return ERROR_TYPE, nil, err
78
	}
79
	str := out.String()
80
	return youtube.getType(str), &str, nil
81
}
82
83
// Video returns unmarshaled data from Youtube
84
func (youtube Youtube) Video(input string) (*VideoResult, error) {
85
	var resp videoResponse
86
	err := json.Unmarshal([]byte(input), &resp)
87
	if err != nil {
88
		return nil, err
89
	}
90
	return &VideoResult{resp.Formats[0].Url, resp.Title}, nil
91
}
92
93
// Playlist returns Playlist
94
func (youtube Youtube) Playlist(input string) (*[]PlaylistVideo, error) {
95
	lines := strings.Split(input, "\n")
96
	videos := make([]PlaylistVideo, 0)
97
	for _, line := range lines {
98
		if len(line) == 0 {
99
			continue
100
		}
101
		var video PlaylistVideo
102
		//fmt.Println("line,", line)
103
		err := json.Unmarshal([]byte(line), &video)
104
		if err != nil {
105
			return nil, err
106
		}
107
		videos = append(videos, video)
108
	}
109
	return &videos, nil
110
}
111
112
func (youtube Youtube) buildUrl(query string) (*string, error) {
0 ignored issues
show
method buildUrl should be buildURL
Loading history...
113
	base := youtube.Conf.General.ServiceURL + "/v1/youtube/search"
114
	address, err := url.Parse(base)
115
	if err != nil {
116
		return nil, err
117
	}
118
	params := url.Values{}
119
	params.Add("search", query)
120
	address.RawQuery = params.Encode()
121
	str := address.String()
122
	return &str, nil
123
}
124
125
// Search returns array of search results
126
func (youtube Youtube) Search(query string) ([]YTSearchContent, error) {
127
	addr, err := youtube.buildUrl(query)
128
	if err != nil {
129
		return nil, err
130
	}
131
	resp, err := http.Get(*addr)
132
	if err != nil {
133
		return nil, err
134
	}
135
	var apiResp ytApiResponse
136
	_ = json.NewDecoder(resp.Body).Decode(&apiResp)
137
	return apiResp.Content, nil
138
}
139