Issues (115)

bot/session.go (5 issues)

Severity
1
package bot
2
3
import (
4
	"errors"
5
	"fmt"
6
	"log"
7
	"os/exec"
8
	"strconv"
9
10
	"github.com/bwmarrin/discordgo"
11
)
12
13
type (
14
	// Session structure with radio player and voice connection
15
	Session struct {
16
		Queue              *SongQueue
17
		Player             RadioPlayer
18
		guildID, ChannelID string
19
		connection         *Connection
20
		Volume             float32
21
	}
22
23
	// SessionManager contains all sessions
24
	SessionManager struct {
25
		sessions map[string]*Session
26
	}
27
28
	// JoinProperties voice connection properties struct
29
	JoinProperties struct {
30
		Muted    bool
31
		Deafened bool
32
	}
33
)
34
35
// Creates and returns new session
36
func newSession(newGuildID, newChannelID string, conn *Connection, volume float32) *Session {
37
	session := &Session{
38
		Queue:      newSongQueue(),
39
		guildID:    newGuildID,
40
		ChannelID:  newChannelID,
41
		connection: conn,
42
		Volume:     volume,
43
	}
44
	return session
45
}
46
47
// GetConnection returns vice connection struct
48
func (sess *Session) GetConnection() *Connection {
49
	return sess.connection
50
}
51
52
// Play starts to play the thing in source
53
func (sess *Session) Play(source string, volume float32) error {
54
	ffmpeg := exec.Command("ffmpeg", "-i", source, "-f", "s16le", "-reconnect", "1", "-reconnect_at_eof", "1", "-reconnect_streamed", "1", "-reconnect_delay_max", "2", "-filter:a", fmt.Sprintf("volume=%.3f", volume), "-ar", strconv.Itoa(FRAME_RATE), "-ac", strconv.Itoa(CHANNELS), "pipe:1")
55
	reader, err := ffmpeg.StdoutPipe()
56
	if err != nil {
57
		return err
58
	}
59
	err = ffmpeg.Start()
60
	if err != nil {
61
		return err
62
	}
63
	defer func() {
64
		reader.Close()
65
		fferr := ffmpeg.Process.Kill()
66
		if fferr != nil {
67
			fmt.Println("FFMPEG close err: ", fferr)
68
		}
69
	}()
70
	return sess.connection.EncodeOpusAndSend(reader)
71
}
72
73
// Stop stops radio
74
func (sess *Session) Stop() {
75
	sess.connection.Stop()
76
}
77
78
// NewSessionManager creates and returns new session manager
79
func NewSessionManager() *SessionManager {
80
	return &SessionManager{make(map[string]*Session)}
81
}
82
83
// GetByGuild returns session by guild ID
84
func (manager *SessionManager) GetByGuild(guildID string) *Session {
85
	for _, sess := range manager.sessions {
86
		if sess.guildID == guildID {
87
			return sess
88
		}
89
	}
90
	return nil
91
}
92
93
// GetByChannel returns session by channel ID
94
func (manager *SessionManager) GetByChannel(channelID string) (*Session, bool) {
95
	sess, found := manager.sessions[channelID]
96
	return sess, found
97
}
98
99
func (manager *SessionManager) GetAll() map[string]*Session {
0 ignored issues
show
exported method SessionManager.GetAll should have comment or be unexported
Loading history...
100
	return manager.sessions
101
}
102
103
func (s *Session) IsOk() bool {
0 ignored issues
show
exported method Session.IsOk should have comment or be unexported
Loading history...
receiver name s should be consistent with previous receiver name sess for Session
Loading history...
104
	if s.connection.voiceConnection != nil {
105
		if s.connection.voiceConnection.Ready == true {
106
			return true
107
		}
108
	}
109
	return false
110
}
111
112
// Join add bot to voice channel
113
func (manager *SessionManager) Join(discord *discordgo.Session, guildID, channelID string,
114
	properties JoinProperties, volume float32) (*Session, error) {
115
	vc, err := discord.ChannelVoiceJoin(guildID, channelID, properties.Muted, properties.Deafened)
116
	if err != nil {
117
		log.Println("Voice connection error: ", err)
118
		if vc != nil {
119
			err := vc.Disconnect()
120
			if err != nil {
121
				log.Println(err)
122
			}
123
			vc.Close()
124
		}
125
		return nil, err
126
	}
127
	log.Println("Voice joined")
128
	if vc == nil {
129
		return nil, errors.New("no voice connection")
130
	}
131
	if vc.Ready != true {
132
		return nil, errors.New("voice connection not ready")
133
	}
134
	log.Println("Voice connection OK and Ready")
135
	sess := newSession(guildID, channelID, NewConnection(vc), volume)
136
	manager.sessions[channelID] = sess
137
	log.Println("Voice session created and saved")
138
	return sess, nil
139
}
140
141
// Leave remove bot from voice channel
142
func (manager *SessionManager) Leave(discord *discordgo.Session, session Session) {
143
	session.connection.Stop()
144
	session.connection.Disconnect()
145
	delete(manager.sessions, session.ChannelID)
146
}
147
148
// Count returns count of voice sessions
149
func (manager *SessionManager) Count() int {
150
	return len(manager.sessions)
151
}
152
153
func (manager *SessionManager) GetChannels() []string {
0 ignored issues
show
exported method SessionManager.GetChannels should have comment or be unexported
Loading history...
154
	var ids []string
155
	for _, s := range manager.sessions {
156
		ids = append(ids, s.ChannelID)
157
	}
158
	return ids
159
}
160
161
func (manager *SessionManager) GetGuilds() []string {
0 ignored issues
show
exported method SessionManager.GetGuilds should have comment or be unexported
Loading history...
162
	var ids []string
163
	for _, s := range manager.sessions {
164
		ids = append(ids, s.guildID)
165
	}
166
	return ids
167
}
168