Some, slightly messy, fixes to get voice -working-.
This commit is contained in:
parent
88492a1dcf
commit
50cc4df965
2 changed files with 63 additions and 35 deletions
21
voice.go
21
voice.go
|
@ -12,7 +12,6 @@ package discordgo
|
||||||
import (
|
import (
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
"net"
|
||||||
"runtime"
|
"runtime"
|
||||||
|
@ -131,16 +130,22 @@ func (v *VoiceConnection) Open() (err error) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// WaitUntilConnected is a TEMP FUNCTION
|
||||||
|
// And this is going to be removed to changed entirely.
|
||||||
|
// I know it looks hacky, but I needed to get it working quickly.
|
||||||
func (v *VoiceConnection) WaitUntilConnected() error {
|
func (v *VoiceConnection) WaitUntilConnected() error {
|
||||||
if v.Ready {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
value, ok := <-v.connected
|
i := 0
|
||||||
|
for {
|
||||||
|
if i > 10 {
|
||||||
|
return fmt.Errorf("Timeout waiting for voice.")
|
||||||
|
}
|
||||||
|
|
||||||
if (!value && !v.Ready) || !ok {
|
if v.Ready {
|
||||||
delete(v.session.VoiceConnections, v.GuildID)
|
return nil
|
||||||
return errors.New("Timed out connecting to voice")
|
}
|
||||||
|
time.Sleep(1 * time.Second)
|
||||||
|
i++
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
|
77
wsapi.go
77
wsapi.go
|
@ -336,52 +336,64 @@ type voiceChannelJoinOp struct {
|
||||||
// cID : Channel ID of the channel to join.
|
// cID : Channel ID of the channel to join.
|
||||||
// mute : If true, you will be set to muted upon joining.
|
// mute : If true, you will be set to muted upon joining.
|
||||||
// deaf : If true, you will be set to deafened upon joining.
|
// deaf : If true, you will be set to deafened upon joining.
|
||||||
// timeout : If greater than zero, the timeout in milliseconds after which connecting will fail
|
// timeout : If timeout > 0 then func will wait up to timeout for voice
|
||||||
|
// connection to be ready. If it does not become ready in that
|
||||||
|
// time frame then it will return an error and close out the voice
|
||||||
|
// connection entirely.
|
||||||
func (s *Session) ChannelVoiceJoin(gID, cID string, mute, deaf bool, timeout int) (voice *VoiceConnection, err error) {
|
func (s *Session) ChannelVoiceJoin(gID, cID string, mute, deaf bool, timeout int) (voice *VoiceConnection, err error) {
|
||||||
// If a voice connection for the guild exists, return that
|
|
||||||
if _, exists := s.VoiceConnections[gID]; exists {
|
|
||||||
return s.VoiceConnections[gID], err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Send the request to Discord that we want to join the voice channel
|
// If a voice connection alreadyy exists for this guild then
|
||||||
data := voiceChannelJoinOp{4, voiceChannelJoinData{&gID, &cID, mute, deaf}}
|
// return that connection. If the channel differs, also change channels.
|
||||||
err = s.wsConn.WriteJSON(data)
|
// TODO: check if the voice connection is really valid or just a shell
|
||||||
if err != nil {
|
// because we might want to allow setting variables prior to getting here
|
||||||
return nil, err
|
// like debug, and other things.
|
||||||
|
if voice, ok := s.VoiceConnections[gID]; ok {
|
||||||
|
if voice.ChannelID != cID {
|
||||||
|
err = voice.ChangeChannel(cID)
|
||||||
|
}
|
||||||
|
return voice, err
|
||||||
|
// TODO: ugh, ugly..
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create a new voice session
|
// Create a new voice session
|
||||||
|
// TODO review what all these things are for....
|
||||||
voice = &VoiceConnection{
|
voice = &VoiceConnection{
|
||||||
Receive: true,
|
Receive: true,
|
||||||
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 this in the waiting map so it can get a session/token
|
// Store voice in VoiceConnections map for thils GuildID
|
||||||
s.VoiceConnections[gID] = voice
|
s.VoiceConnections[gID] = voice
|
||||||
|
|
||||||
// Store gID and cID for later use
|
// Send the request to Discord that we want to join the voice channel
|
||||||
voice.GuildID = gID
|
data := voiceChannelJoinOp{4, voiceChannelJoinData{&gID, &cID, mute, deaf}}
|
||||||
voice.ChannelID = cID
|
err = s.wsConn.WriteJSON(data)
|
||||||
|
if err != nil {
|
||||||
// Queue the timeout in case we fail to connect
|
return
|
||||||
if timeout > 0 {
|
|
||||||
go func() {
|
|
||||||
time.Sleep(time.Millisecond * time.Duration(timeout))
|
|
||||||
if !voice.Ready {
|
|
||||||
voice.connected <- false
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return voice, err
|
// doesn't exactly work perfect yet.. TODO
|
||||||
|
if timeout > 0 {
|
||||||
|
err = voice.WaitUntilConnected()
|
||||||
|
if err != nil {
|
||||||
|
voice.Close()
|
||||||
|
delete(s.VoiceConnections, gID)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// onVoiceStateUpdate handles Voice State Update events on the data
|
// onVoiceStateUpdate handles Voice State Update events on the data
|
||||||
// websocket. This comes immediately after the call to VoiceChannelJoin
|
// websocket. This comes immediately after the call to VoiceChannelJoin
|
||||||
// for the session user.
|
// for the session user.
|
||||||
func (s *Session) onVoiceStateUpdate(se *Session, st *VoiceStateUpdate) {
|
func (s *Session) onVoiceStateUpdate(se *Session, st *VoiceStateUpdate) {
|
||||||
|
|
||||||
// If we don't have a connection for the channel, don't bother
|
// If we don't have a connection for the channel, don't bother
|
||||||
if st.ChannelID == "" {
|
if st.ChannelID == "" {
|
||||||
return
|
return
|
||||||
|
@ -409,7 +421,10 @@ func (s *Session) onVoiceStateUpdate(se *Session, st *VoiceStateUpdate) {
|
||||||
|
|
||||||
// Store the SessionID for later use.
|
// Store the SessionID for later use.
|
||||||
voice.UserID = self.ID // TODO: Review
|
voice.UserID = self.ID // TODO: Review
|
||||||
voice.sessionRecv <- st.SessionID
|
voice.sessionID = st.SessionID
|
||||||
|
|
||||||
|
// TODO: Consider this...
|
||||||
|
// voice.sessionRecv <- st.SessionID
|
||||||
}
|
}
|
||||||
|
|
||||||
// onVoiceServerUpdate handles the Voice Server Update data websocket event.
|
// onVoiceServerUpdate handles the Voice Server Update data websocket event.
|
||||||
|
@ -420,10 +435,12 @@ func (s *Session) onVoiceStateUpdate(se *Session, st *VoiceStateUpdate) {
|
||||||
// to a voice channel. In that case, need to re-establish connection to
|
// to a voice channel. In that case, need to re-establish connection to
|
||||||
// the new region endpoint.
|
// the new region endpoint.
|
||||||
func (s *Session) onVoiceServerUpdate(se *Session, st *VoiceServerUpdate) {
|
func (s *Session) onVoiceServerUpdate(se *Session, st *VoiceServerUpdate) {
|
||||||
|
|
||||||
voice, exists := s.VoiceConnections[st.GuildID]
|
voice, exists := s.VoiceConnections[st.GuildID]
|
||||||
|
|
||||||
// If no VoiceConnection exists, just skip this
|
// If no VoiceConnection exists, just skip this
|
||||||
if !exists {
|
if !exists {
|
||||||
|
fmt.Println("doesn't exist! Oh noooo bail out.. emergency..")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -434,10 +451,16 @@ func (s *Session) onVoiceServerUpdate(se *Session, st *VoiceServerUpdate) {
|
||||||
|
|
||||||
// If currently connected to voice ws/udp, then disconnect.
|
// If currently connected to voice ws/udp, then disconnect.
|
||||||
// Has no effect if not connected.
|
// Has no effect if not connected.
|
||||||
voice.Close()
|
// voice.Close()
|
||||||
|
|
||||||
// Wait for the sessionID from onVoiceStateUpdate
|
// Wait for the sessionID from onVoiceStateUpdate
|
||||||
voice.sessionID = <-voice.sessionRecv
|
// voice.sessionID = <-voice.sessionRecv
|
||||||
|
// TODO review above
|
||||||
|
// wouldn't this cause a huge problem, if it's just a guild server
|
||||||
|
// update.. ?
|
||||||
|
// I could add a timeout loop of some sort and also check if the
|
||||||
|
// sessionID doesn't or does exist already...
|
||||||
|
// something.. a bit smarter.
|
||||||
|
|
||||||
// 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.
|
||||||
|
|
Loading…
Reference in a new issue