From b48e8c992ed442a5ba05e5cc3165f880979d1331 Mon Sep 17 00:00:00 2001 From: andrei Date: Sat, 5 Mar 2016 03:53:42 -0800 Subject: [PATCH] Track voice state changes, expose stuff, add channel changing --- state.go | 41 +++++++++++++++++++++++++++++++++++++++++ structs.go | 1 + voice.go | 23 ++++++++++++++++++----- wsapi.go | 21 +++++++-------------- 4 files changed, 67 insertions(+), 19 deletions(-) diff --git a/state.go b/state.go index 2bdf35f..a9dbbdf 100644 --- a/state.go +++ b/state.go @@ -453,6 +453,45 @@ func (s *State) MessageRemove(message *Message) error { return errors.New("Message not found.") } +func (s *State) VoiceStateUpdate(update *VoiceStateUpdate) error { + var exists bool + var guild *Guild + + for _, guild = range s.Guilds { + if guild.ID == update.GuildID { + exists = true + break + } + } + + if !exists { + return nil + } + + // Handle Leaving Channel + if update.ChannelID == "" { + for i, state := range guild.VoiceStates { + if state.UserID == update.UserID { + guild.VoiceStates = append(guild.VoiceStates[:i], guild.VoiceStates[i+1:]...) + } + } + } else { + exists := false + for _, state := range guild.VoiceStates { + if state.UserID == update.UserID { + state.ChannelID = update.ChannelID + exists = true + } + } + + if !exists { + guild.VoiceStates = append(guild.VoiceStates, update.VoiceState) + } + } + + return nil +} + // Message gets a message by channel and message ID. func (s *State) Message(channelID, messageID string) (*Message, error) { if s == nil { @@ -514,6 +553,8 @@ func (s *State) onInterface(se *Session, i interface{}) (err error) { err = s.MessageAdd(t.Message) case *MessageDelete: err = s.MessageRemove(t.Message) + case *VoiceStateUpdate: + err = s.VoiceStateUpdate(t) } return diff --git a/structs.go b/structs.go index 54c8eab..9ffa96e 100644 --- a/structs.go +++ b/structs.go @@ -203,6 +203,7 @@ type VoiceState struct { UserID string `json:"user_id"` SessionID string `json:"session_id"` ChannelID string `json:"channel_id"` + GuildID string `json:"guild_id"` Suppress bool `json:"suppress"` SelfMute bool `json:"self_mute"` SelfDeaf bool `json:"self_deaf"` diff --git a/voice.go b/voice.go index fa32456..9d67ed5 100644 --- a/voice.go +++ b/voice.go @@ -36,6 +36,9 @@ type VoiceConnection struct { OP2 *voiceOP2 // exported for dgvoice, may change. OpusSend chan []byte // Chan for sending opus audio OpusRecv chan *Packet // Chan for receiving opus audio + GuildID string + ChannelID string + UserID string // 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 @@ -46,9 +49,6 @@ type VoiceConnection struct { sessionID string token string endpoint string - guildID string - channelID string - userID string op4 voiceOP4 // Used to send a close signal to goroutines @@ -114,7 +114,7 @@ func (v *VoiceConnection) Open() (err error) { return } - data := voiceHandshakeOp{0, voiceHandshakeData{v.guildID, v.userID, v.sessionID, v.token}} + data := voiceHandshakeOp{0, voiceHandshakeData{v.GuildID, v.UserID, v.sessionID, v.token}} err = v.wsConn.WriteJSON(data) if err != nil { @@ -604,7 +604,7 @@ func (v *VoiceConnection) Close() { defer v.Unlock() if v.Ready { - data := voiceChannelJoinOp{4, voiceChannelJoinData{&v.guildID, nil, true, true}} + data := voiceChannelJoinOp{4, voiceChannelJoinData{&v.GuildID, nil, true, true}} v.session.wsConn.WriteJSON(data) } @@ -631,3 +631,16 @@ func (v *VoiceConnection) Close() { v.wsConn = nil } } + +// Change channels +func (v *VoiceConnection) ChangeChannel(channelID string) (err error) { + data := voiceChannelJoinOp{4, voiceChannelJoinData{&v.GuildID, &channelID, true, true}} + + err = v.session.wsConn.WriteJSON(data) + + if err == nil { + v.ChannelID = channelID + } + + return err +} diff --git a/wsapi.go b/wsapi.go index 9e93b20..d177a96 100644 --- a/wsapi.go +++ b/wsapi.go @@ -356,8 +356,8 @@ func (s *Session) ChannelVoiceJoin(gID, cID string, mute, deaf bool) (voice *Voi s.VoiceConnections[gID] = voice // Store gID and cID for later use - voice.guildID = gID - voice.channelID = cID + voice.GuildID = gID + voice.ChannelID = cID return voice, err } @@ -371,13 +371,8 @@ func (s *Session) onVoiceStateUpdate(se *Session, st *VoiceStateUpdate) { return } - channel, err := s.Channel(st.ChannelID) - if err != nil { - fmt.Println(err) - return - } - - voice, exists := s.VoiceConnections[channel.GuildID] + // Check if we have a voice connection to update + voice, exists := s.VoiceConnections[st.GuildID] if !exists { return } @@ -391,15 +386,13 @@ func (s *Session) onVoiceStateUpdate(se *Session, st *VoiceStateUpdate) { return } - // This event comes for all users, if it's not for the session - // user just ignore it. - // TODO Move this IF to the event() func + // We only care about events that are about us if st.UserID != self.ID { return } // Store the SessionID for later use. - voice.userID = self.ID // TODO: Review + voice.UserID = self.ID // TODO: Review voice.sessionRecv <- st.SessionID } @@ -421,7 +414,7 @@ func (s *Session) onVoiceServerUpdate(se *Session, st *VoiceServerUpdate) { // Store values for later use voice.token = st.Token voice.endpoint = st.Endpoint - voice.guildID = st.GuildID + voice.GuildID = st.GuildID // If currently connected to voice ws/udp, then disconnect. // Has no effect if not connected.