func (c *Client) Connect(ctx context.Context) error {
	c.mu.Lock()
	defer c.mu.Unlock()
	if c.isConnected() {
		return discord.ErrGatewayAlreadyConnected
	}
	c.connecting.Store(true)
	defer c.connecting.Store(false)
	var err error
	if c.gatewayURL == "" {
		c.gatewayURL, err = c.Gateway(ctx)
		if err != nil {
			return fmt.Errorf("could not get gateway URL: %w", err)
		}
	}
	c.voicePayloads = make(chan *payload.Payload)
	c.error = make(chan error)
	c.reportErrorOnce = sync.Once{}
	c.stop = make(chan struct{})
	c.ctx, c.cancel = context.WithCancel(context.Background())
	header := make(http.Header)
	header.Add("Accept-Encoding", "zlib")
	gwURL := fmt.Sprintf("%s?v=%s&encoding=%s", c.gatewayURL, version.Gateway(), gatewayEncoding)
	c.logger.Debugf("connecting to the gateway: %s", gwURL)
	c.conn, _, err = websocket.Dial(ctx, gwURL, &websocket.DialOptions{HTTPHeader: header})
	if err != nil {
		return err
	}
	defer func() {
		if err != nil {
			_ = c.conn.Close(websocket.StatusInternalError, "failed to establish connection")  
			c.connected.Store(false)
			close(c.stop)
			c.cancel()
		}
	}()
	p, err := c.recvPayload()
	if err != nil {
		return fmt.Errorf("could not receive payload from gateway: %w", err)
	}
	if p.Op != gatewayOpcodeHello {
		return fmt.Errorf("expected Opcode 10 Hello; got Opcode %d", p.Op)
	}
	var hello struct {
		HeartbeatInterval int `json:"heartbeat_interval"`
	}
	if err = json.Unmarshal(p.D, &hello); err != nil {
		return err
	}
	seq := c.sequence.Load()
	if seq == 0 && c.sessionID == "" {
		c.logger.Debug("identifying to the gateway")
		if err = c.identify(ctx); err != nil {
			return err
		}
		if err = c.recvReady(); err != nil {
			return err
		}
	} else {
		c.logger.Debugf("trying to resume an existing session (seq=%d; sessID=%q)", seq, c.sessionID)
		if err = c.resume(ctx); err != nil {
			return err
		}
	}
	c.wg.Add(1)
	go c.wait()
	c.wg.Add(1)
	go c.heartbeat(time.Duration(hello.HeartbeatInterval) * time.Millisecond)
	c.wg.Add(1)
	go c.listenAndHandlePayloads()
	return nil
}
Connect connects and identifies the client to the Discord Gateway.
package harmony
import (
	"context"
	"encoding/json"
	"errors"
	"fmt"
	"net/http"
	"sync"
	"time"
	"github.com/skwair/harmony/discord"
	"github.com/skwair/harmony/internal/payload"
	"github.com/skwair/harmony/version"
	"nhooyr.io/websocket"
)
const gatewayEncoding = "json"
var errMustReconnect = errors.New("must reconnect to the Gateway")