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  }