123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109 |
- package remoteauth
- import (
- "context"
- "crypto/rand"
- "crypto/rsa"
- "crypto/sha256"
- "encoding/base64"
- "encoding/json"
- "net/http"
- "github.com/gorilla/websocket"
- )
- type Client struct {
- URL string
- Origin string
- conn *websocket.Conn
- qrChan chan string
- doneChan chan struct{}
- user User
- err error
- heartbeats int
- closed bool
- privateKey *rsa.PrivateKey
- }
- // New creates a new Discord remote auth client. qrChan is a channel that will
- // receive the qrcode once it is available.
- func New() (*Client, error) {
- privateKey, err := rsa.GenerateKey(rand.Reader, 2048)
- if err != nil {
- return nil, err
- }
- return &Client{
- URL: "wss://remote-auth-gateway.discord.gg/?v=1",
- Origin: "https://discord.com",
- privateKey: privateKey,
- }, nil
- }
- // Dialo will start the QRCode login process. ctx may be used to abandon the
- // process.
- func (c *Client) Dial(ctx context.Context, qrChan chan string, doneChan chan struct{}) error {
- header := http.Header{
- "Origin": []string{c.Origin},
- }
- c.qrChan = qrChan
- c.doneChan = doneChan
- conn, _, err := websocket.DefaultDialer.DialContext(ctx, c.URL, header)
- if err != nil {
- return err
- }
- c.conn = conn
- go c.processMessages()
- return nil
- }
- func (c *Client) Result() (User, error) {
- return c.user, c.err
- }
- func (c *Client) close() error {
- if c.closed {
- return nil
- }
- c.conn.WriteMessage(
- websocket.CloseMessage,
- websocket.FormatCloseMessage(websocket.CloseNormalClosure, ""),
- )
- c.closed = true
- defer close(c.doneChan)
- return c.conn.Close()
- }
- func (c *Client) write(p clientPacket) error {
- payload, err := json.Marshal(p)
- if err != nil {
- return err
- }
- return c.conn.WriteMessage(websocket.TextMessage, payload)
- }
- func (c *Client) decrypt(payload string) ([]byte, error) {
- // Decode the base64 string.
- raw, err := base64.StdEncoding.DecodeString(payload)
- if err != nil {
- return []byte{}, err
- }
- // Decrypt the data.
- return rsa.DecryptOAEP(sha256.New(), nil, c.privateKey, raw, nil)
- }
|