More cleanup, moving things around..

This commit is contained in:
Bruce Marriner 2016-03-17 15:54:07 -05:00
parent cab4964d3a
commit 513facf391
2 changed files with 88 additions and 97 deletions

179
voice.go
View file

@ -40,9 +40,6 @@ type VoiceConnection struct {
OpusSend chan []byte // Chan for sending opus audio OpusSend chan []byte // Chan for sending opus audio
OpusRecv chan *Packet // Chan for receiving opus audio OpusRecv chan *Packet // Chan for receiving opus audio
// FrameRate int // This can be used to set the FrameRate of Opus data
// FrameSize int // This can be used to set the FrameSize of Opus data
wsConn *websocket.Conn wsConn *websocket.Conn
udpConn *net.UDPConn udpConn *net.UDPConn
session *Session session *Session
@ -50,8 +47,6 @@ type VoiceConnection struct {
sessionID string sessionID string
token string token string
endpoint string endpoint string
op4 voiceOP4
op2 voiceOP2
// Used to send a close signal to goroutines // Used to send a close signal to goroutines
close chan struct{} close chan struct{}
@ -61,81 +56,43 @@ type VoiceConnection struct {
// Used to pass the sessionid from onVoiceStateUpdate // Used to pass the sessionid from onVoiceStateUpdate
sessionRecv chan string sessionRecv chan string
op4 voiceOP4
op2 voiceOP2
} }
// ------------------------------------------------------------------------------------------------ // Speaking sends a speaking notification to Discord over the voice websocket.
// Code related to the VoiceConnection websocket connection // This must be sent as true prior to sending audio and should be set to false
// ------------------------------------------------------------------------------------------------ // once finished sending audio.
// b : Send true if speaking, false if not.
func (v *VoiceConnection) Speaking(b bool) (err error) {
// A voiceOP4 stores the data for the voice operation 4 websocket event type voiceSpeakingData struct {
// which provides us with the NaCl SecretBox encryption key Speaking bool `json:"speaking"`
type voiceOP4 struct { Delay int `json:"delay"`
SecretKey [32]byte `json:"secret_key"`
Mode string `json:"mode"`
}
// A voiceOP2 stores the data for the voice operation 2 websocket event
// which is sort of like the voice READY packet
type voiceOP2 struct {
SSRC uint32 `json:"ssrc"`
Port int `json:"port"`
Modes []string `json:"modes"`
HeartbeatInterval time.Duration `json:"heartbeat_interval"`
}
type voiceHandshakeData struct {
ServerID string `json:"server_id"`
UserID string `json:"user_id"`
SessionID string `json:"session_id"`
Token string `json:"token"`
}
type voiceHandshakeOp struct {
Op int `json:"op"` // Always 0
Data voiceHandshakeData `json:"d"`
}
// Open opens a voice connection. This should be called
// after VoiceChannelJoin is used and the data VOICE websocket events
// are captured.
func (v *VoiceConnection) Open() (err error) {
v.Lock()
defer v.Unlock()
// Don't open a websocket if one is already open
if v.wsConn != nil {
return
} }
// Connect to VoiceConnection Websocket type voiceSpeakingOp struct {
vg := fmt.Sprintf("wss://%s", strings.TrimSuffix(v.endpoint, ":80")) Op int `json:"op"` // Always 5
v.wsConn, _, err = websocket.DefaultDialer.Dial(vg, nil) Data voiceSpeakingData `json:"d"`
if err != nil {
fmt.Println("VOICE error opening websocket:", err)
return
} }
data := voiceHandshakeOp{0, voiceHandshakeData{v.GuildID, v.UserID, v.sessionID, v.token}} if v.wsConn == nil {
return fmt.Errorf("No VoiceConnection websocket.")
}
data := voiceSpeakingOp{5, voiceSpeakingData{b, 0}}
err = v.wsConn.WriteJSON(data) err = v.wsConn.WriteJSON(data)
if err != nil { if err != nil {
fmt.Println("VOICE error sending init packet:", err) fmt.Println("Speaking() write json error:", err)
return return
} }
// Start a listening for voice websocket events
// TODO add a check here to make sure Listen worked by monitoring
// a chan or bool?
v.close = make(chan struct{})
go v.wsListen(v.wsConn, v.close)
return return
} }
// WaitUntilConnected is a TEMP FUNCTION // WaitUntilConnected waits for the Voice Connection to
// And this is going to be removed or changed entirely. // become ready, if it does not become ready it retuns an err
// I know it looks hacky, but I needed to get it working quickly.
func (v *VoiceConnection) WaitUntilConnected() error { func (v *VoiceConnection) WaitUntilConnected() error {
i := 0 i := 0
@ -155,36 +112,6 @@ func (v *VoiceConnection) WaitUntilConnected() error {
return nil return nil
} }
type voiceSpeakingData struct {
Speaking bool `json:"speaking"`
Delay int `json:"delay"`
}
type voiceSpeakingOp struct {
Op int `json:"op"` // Always 5
Data voiceSpeakingData `json:"d"`
}
// Speaking sends a speaking notification to Discord over the voice websocket.
// This must be sent as true prior to sending audio and should be set to false
// once finished sending audio.
// b : Send true if speaking, false if not.
func (v *VoiceConnection) Speaking(b bool) (err error) {
if v.wsConn == nil {
return fmt.Errorf("No VoiceConnection websocket.")
}
data := voiceSpeakingOp{5, voiceSpeakingData{b, 0}}
err = v.wsConn.WriteJSON(data)
if err != nil {
fmt.Println("Speaking() write json error:", err)
return
}
return
}
// ChangeChannel sends Discord a request to change channels within a Guild // ChangeChannel sends Discord a request to change channels within a Guild
// !!! NOTE !!! This function may be removed in favour of just using ChannelVoiceJoin // !!! NOTE !!! This function may be removed in favour of just using ChannelVoiceJoin
func (v *VoiceConnection) ChangeChannel(channelID string, mute, deaf bool) (err error) { func (v *VoiceConnection) ChangeChannel(channelID string, mute, deaf bool) (err error) {
@ -249,6 +176,70 @@ func (v *VoiceConnection) Close() {
// Unexported Internal Functions Below. // Unexported Internal Functions Below.
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// A voiceOP4 stores the data for the voice operation 4 websocket event
// which provides us with the NaCl SecretBox encryption key
type voiceOP4 struct {
SecretKey [32]byte `json:"secret_key"`
Mode string `json:"mode"`
}
// A voiceOP2 stores the data for the voice operation 2 websocket event
// which is sort of like the voice READY packet
type voiceOP2 struct {
SSRC uint32 `json:"ssrc"`
Port int `json:"port"`
Modes []string `json:"modes"`
HeartbeatInterval time.Duration `json:"heartbeat_interval"`
}
// Open opens a voice connection. This should be called
// after VoiceChannelJoin is used and the data VOICE websocket events
// are captured.
func (v *VoiceConnection) open() (err error) {
v.Lock()
defer v.Unlock()
// Don't open a websocket if one is already open
if v.wsConn != nil {
return
}
// Connect to VoiceConnection Websocket
vg := fmt.Sprintf("wss://%s", strings.TrimSuffix(v.endpoint, ":80"))
v.wsConn, _, err = websocket.DefaultDialer.Dial(vg, nil)
if err != nil {
fmt.Println("VOICE error opening websocket:", err)
return
}
type voiceHandshakeData struct {
ServerID string `json:"server_id"`
UserID string `json:"user_id"`
SessionID string `json:"session_id"`
Token string `json:"token"`
}
type voiceHandshakeOp struct {
Op int `json:"op"` // Always 0
Data voiceHandshakeData `json:"d"`
}
data := voiceHandshakeOp{0, voiceHandshakeData{v.GuildID, v.UserID, v.sessionID, v.token}}
err = v.wsConn.WriteJSON(data)
if err != nil {
fmt.Println("VOICE error sending init packet:", err)
return
}
// Start a listening for voice websocket events
// TODO add a check here to make sure Listen worked by monitoring
// a chan or bool?
v.close = make(chan struct{})
go v.wsListen(v.wsConn, v.close)
return
}
// wsListen listens on the voice websocket for messages and passes them // wsListen listens on the voice websocket for messages and passes them
// to the voice event handler. This is automatically called by the Open func // to the voice event handler. This is automatically called by the Open func
func (v *VoiceConnection) wsListen(wsConn *websocket.Conn, close <-chan struct{}) { func (v *VoiceConnection) wsListen(wsConn *websocket.Conn, close <-chan struct{}) {

View file

@ -352,11 +352,11 @@ func (s *Session) ChannelVoiceJoin(gID, cID string, mute, deaf bool) (voice *Voi
// Create a new voice session // Create a new voice session
// TODO review what all these things are for.... // TODO review what all these things are for....
voice = &VoiceConnection{ voice = &VoiceConnection{
GuildID: gID,
ChannelID: cID,
session: s, session: s,
connected: make(chan bool), connected: make(chan bool),
sessionRecv: make(chan string), sessionRecv: make(chan string),
GuildID: gID,
ChannelID: cID,
} }
// Store voice in VoiceConnections map for this GuildID // Store voice in VoiceConnections map for this GuildID
@ -451,7 +451,7 @@ func (s *Session) onVoiceServerUpdate(se *Session, st *VoiceServerUpdate) {
// We now have enough information to open a voice websocket conenction // We now have enough information to open a voice websocket conenction
// so, that's what the next call does. // so, that's what the next call does.
err := voice.Open() err := voice.open()
if err != nil { if err != nil {
fmt.Println("onVoiceServerUpdate Voice.Open error: ", err) fmt.Println("onVoiceServerUpdate Voice.Open error: ", err)
// TODO better logging // TODO better logging