Passed
Push — master ( f7aab9...4f517e )
by Viktor
01:53
created

bot.TwitchInit   A

Complexity

Conditions 5

Size

Total Lines 11
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 5
eloc 9
nop 3
dl 0
loc 11
rs 9.3333
c 0
b 0
f 0
1
package bot
2
3
import (
4
	"encoding/json"
5
	"errors"
6
	"fmt"
7
	"github.com/bwmarrin/discordgo"
8
	"net/http"
9
	"strings"
10
	"time"
11
)
12
13
type Twitch struct {
0 ignored issues
show
introduced by
exported type Twitch should have comment or be unexported
Loading history...
14
	Streams []*TwitchStream
15
	Guilds  map[string]*TwitchGuild
16
	DB      *DBWorker
17
	Conf    *Config
18
	Discord *discordgo.Session
19
}
20
21
type TwitchGuild struct {
0 ignored issues
show
introduced by
exported type TwitchGuild should have comment or be unexported
Loading history...
22
	ID      string
23
	Streams []*TwitchStream
24
}
25
26
type TwitchStream struct {
0 ignored issues
show
introduced by
exported type TwitchStream should have comment or be unexported
Loading history...
27
	Login          string
28
	Guild          string
29
	Channel        string
30
	IsOnline       bool
31
	IsCustom       bool
32
	CustomMessage  string
33
	CustomImageURI string
34
}
35
36
type TwitchStreamResult struct {
0 ignored issues
show
introduced by
exported type TwitchStreamResult should have comment or be unexported
Loading history...
37
	Data []TwitchStreamData `json:"data"`
38
}
39
40
type TwitchStreamData struct {
0 ignored issues
show
introduced by
exported type TwitchStreamData should have comment or be unexported
Loading history...
41
	ID           string `json:"id"`
42
	UserID       string `json:"user_id"`
43
	UserName     string `json:"user_name"`
44
	GameID       string `json:"game_id"`
45
	Type         string `json:"type"`
46
	Title        string `json:"title"`
47
	Viewers      int    `json:"viewer_count"`
48
	Language     string `json:"language"`
49
	ThumbnailURL string `json:"thumbnail_url"`
50
}
51
52
type TwitchUserResult struct {
0 ignored issues
show
introduced by
exported type TwitchUserResult should have comment or be unexported
Loading history...
53
	Data []TwitchUserData `json:"data"`
54
}
55
56
type TwitchUserData struct {
0 ignored issues
show
introduced by
exported type TwitchUserData should have comment or be unexported
Loading history...
57
	ID              string `json:"id"`
58
	Login           string `json:"login"`
59
	Name            string `json:"display_name"`
60
	Type            string `json:"type"`
61
	BroadcasterType string `json:"broadcaster_type"`
62
	Description     string `json:"description"`
63
	ProfileImgURL   string `json:"profile_image_url"`
64
	OfflineImgURL   string `json:"offline_image_url"`
65
	Views           int    `json:"view_count"`
66
}
67
68
// TwitchInit makes new instance of twitch api worker
69
func TwitchInit(session *discordgo.Session, conf *Config, db *DBWorker) *Twitch {
70
	guilds := make(map[string]*TwitchGuild)
71
	var streams []*TwitchStream
72
	for _, g := range session.State.Guilds {
73
		guildStreams := db.GetTwitchStreams(g.ID)
74
		for _, s := range guildStreams {
75
			streams = append(streams, s)
76
		}
77
		guilds[g.ID] = &TwitchGuild{g.ID, guildStreams}
78
	}
79
	return &Twitch{streams, guilds, db, conf, session}
80
}
81
82
// Update updates status of streamers and notify
83
func (t *Twitch) Update() {
84
	for _, s := range t.Streams {
85
		timeout := time.Duration(time.Duration(1) * time.Second)
86
		client := &http.Client{
87
			Timeout: time.Duration(timeout),
88
		}
89
		req, _ := http.NewRequest("GET", fmt.Sprintf("https://api.twitch.tv/helix/streams?user_login=%v", s.Login), nil)
90
		req.Header.Add("Client-ID", t.Conf.Twitch.ClientID)
91
		resp, err := client.Do(req)
92
		var result TwitchStreamResult
93
		if err == nil {
94
			err = json.NewDecoder(resp.Body).Decode(&result)
95
			if err != nil {
96
				t.DB.Log("Twitch", "", "Parsing Twitch API stream error")
97
				continue
98
			}
99
			if len(result.Data) > 0 {
100
				if s.IsOnline == false {
101
					s.IsOnline = true
102
					imgUrl := strings.Replace(result.Data[0].ThumbnailURL, "{width}", "720", -1)
0 ignored issues
show
introduced by
var imgUrl should be imgURL
Loading history...
103
					imgUrl = strings.Replace(imgUrl, "{height}", "480", -1)
104
					emb := NewEmbed(fmt.Sprintf("Hey @here %v is now live on https://www.twitch.tv/%v", result.Data[0].UserName, s.Login)).
105
						Field("Stream", result.Data[0].Title, true).
106
						AttachImgURL(imgUrl)
107
					_, _ = t.Discord.ChannelMessageSendEmbed(s.Channel, emb.GetEmbed())
108
				}
109
			} else {
110
				if s.IsOnline == true {
111
					s.IsOnline = false
112
				}
113
			}
114
			t.DB.UpdateStream(s)
115
		}
116
	}
117
}
118
119
// AddStreamer adds new streamer to list
120
func (t *Twitch) AddStreamer(guild, channel, login string) error {
121
	timeout := time.Duration(time.Duration(1) * time.Second)
122
	client := &http.Client{
123
		Timeout: time.Duration(timeout),
124
	}
125
	req, _ := http.NewRequest("GET", fmt.Sprintf("https://api.twitch.tv/helix/users?login=%v", login), nil)
126
	req.Header.Add("Client-ID", t.Conf.Twitch.ClientID)
127
	resp, err := client.Do(req)
128
	var result TwitchUserResult
129
	if err == nil {
130
		err = json.NewDecoder(resp.Body).Decode(&result)
131
		if err != nil {
132
			return errors.New("parsing streamer error")
133
		}
134
		if len(result.Data) > 0 {
135
			stream := TwitchStream{}
136
			stream.Login = login
137
			stream.Channel = channel
138
			stream.Guild = guild
139
			t.Streams = append(t.Streams, &stream)
140
			t.Guilds[guild].Streams = append(t.Guilds[guild].Streams, &stream)
141
			t.DB.AddStream(&stream)
142
		}
143
	} else {
144
		return errors.New("getting streamer error")
145
	}
146
	return nil
147
}
148
149
// RemoveStreamer removes streamer from list
150
func (t *Twitch) RemoveStreamer(login, guild string) error {
151
	complete := false
152
	for i, s := range t.Guilds[guild].Streams {
153
		if s.Guild == guild && s.Login == login {
154
			t.Guilds[guild].Streams = append(t.Guilds[guild].Streams[:i], t.Guilds[guild].Streams[i+1:]...)
155
			complete = true
156
		}
157
	}
158
	for i, s := range t.Streams {
159
		if s.Guild == guild && s.Login == login {
160
			t.Streams = append(t.Streams[:i], t.Streams[i+1:]...)
161
			complete = true
162
		}
163
	}
164
	if !complete {
165
		return errors.New("streamer not found")
166
	}
167
	return nil
168
}
169