github.com/diamondburned/arikawa/v2@v2.1.0/voice/voicegateway/op.go (about) 1 package voicegateway 2 3 import ( 4 "fmt" 5 "sync" 6 7 "github.com/diamondburned/arikawa/v2/utils/json" 8 "github.com/diamondburned/arikawa/v2/utils/wsutil" 9 "github.com/pkg/errors" 10 ) 11 12 // OPCode represents a Discord Gateway Gateway operation code. 13 type OPCode = wsutil.OPCode 14 15 const ( 16 IdentifyOP OPCode = 0 // send 17 SelectProtocolOP OPCode = 1 // send 18 ReadyOP OPCode = 2 // receive 19 HeartbeatOP OPCode = 3 // send 20 SessionDescriptionOP OPCode = 4 // receive 21 SpeakingOP OPCode = 5 // send/receive 22 HeartbeatAckOP OPCode = 6 // receive 23 ResumeOP OPCode = 7 // send 24 HelloOP OPCode = 8 // receive 25 ResumedOP OPCode = 9 // receive 26 ClientConnectOP OPCode = 12 // receive 27 ClientDisconnectOP OPCode = 13 // receive 28 ) 29 30 func (c *Gateway) HandleOP(op *wsutil.OP) error { 31 wsutil.WSDebug("Handle OP", op.Code) 32 switch op.Code { 33 // Gives information required to make a UDP connection 34 case ReadyOP: 35 if err := unmarshalMutex(op.Data, &c.ready, &c.mutex); err != nil { 36 return errors.Wrap(err, "failed to parse READY event") 37 } 38 39 c.Events <- &c.ready 40 41 // Gives information about the encryption mode and secret key for sending voice packets 42 case SessionDescriptionOP: 43 // ? 44 // Already handled by Session. 45 46 // Someone started or stopped speaking. 47 case SpeakingOP: 48 ev := new(SpeakingEvent) 49 50 if err := json.Unmarshal(op.Data, ev); err != nil { 51 return errors.Wrap(err, "failed to parse Speaking event") 52 } 53 54 c.Events <- ev 55 56 // Heartbeat response from the server 57 case HeartbeatAckOP: 58 c.EventLoop.Echo() 59 60 // Hello server, we hear you! :) 61 case HelloOP: 62 // ? 63 // Already handled on initial connection. 64 65 // Server is saying the connection was resumed, no data here. 66 case ResumedOP: 67 wsutil.WSDebug("Gateway connection has been resumed.") 68 69 case ClientConnectOP: 70 ev := new(ClientConnectEvent) 71 72 if err := json.Unmarshal(op.Data, ev); err != nil { 73 return errors.Wrap(err, "failed to parse Speaking event") 74 } 75 76 c.Events <- ev 77 78 case ClientDisconnectOP: 79 ev := new(ClientDisconnectEvent) 80 81 if err := json.Unmarshal(op.Data, ev); err != nil { 82 return errors.Wrap(err, "failed to parse Speaking event") 83 } 84 85 c.Events <- ev 86 87 default: 88 return fmt.Errorf("unknown OP code %d", op.Code) 89 } 90 91 return nil 92 } 93 94 func unmarshalMutex(d []byte, v interface{}, m *sync.RWMutex) error { 95 m.Lock() 96 err := json.Unmarshal(d, v) 97 m.Unlock() 98 return err 99 }