github.com/diamondburned/arikawa/v2@v2.1.0/gateway/identify.go (about)

     1  package gateway
     2  
     3  import (
     4  	"context"
     5  	"runtime"
     6  	"time"
     7  
     8  	"github.com/pkg/errors"
     9  	"golang.org/x/time/rate"
    10  )
    11  
    12  // DefaultPresence is used as the default presence when initializing a new
    13  // Gateway.
    14  var DefaultPresence *UpdateStatusData
    15  
    16  // Identifier is a wrapper around IdentifyData to add in appropriate rate
    17  // limiters.
    18  type Identifier struct {
    19  	IdentifyData
    20  
    21  	IdentifyShortLimit  *rate.Limiter `json:"-"` // optional
    22  	IdentifyGlobalLimit *rate.Limiter `json:"-"` // optional
    23  }
    24  
    25  // DefaultIdentifier creates a new default Identifier
    26  func DefaultIdentifier(token string) *Identifier {
    27  	return NewIdentifier(DefaultIdentifyData(token))
    28  }
    29  
    30  // NewIdentifier creates a new identifier with the given IdentifyData and
    31  // default rate limiters.
    32  func NewIdentifier(data IdentifyData) *Identifier {
    33  	return &Identifier{
    34  		IdentifyData:        data,
    35  		IdentifyShortLimit:  rate.NewLimiter(rate.Every(5*time.Second), 1),
    36  		IdentifyGlobalLimit: rate.NewLimiter(rate.Every(24*time.Hour), 1000),
    37  	}
    38  }
    39  
    40  // Wait waits for the rate limiters to pass. If a limiter is nil, then it will
    41  // not be used to wait. This is useful
    42  func (i *Identifier) Wait(ctx context.Context) error {
    43  	if i.IdentifyShortLimit != nil {
    44  		if err := i.IdentifyShortLimit.Wait(ctx); err != nil {
    45  			return errors.Wrap(err, "can't wait for short limit")
    46  		}
    47  	}
    48  
    49  	if i.IdentifyGlobalLimit != nil {
    50  		if err := i.IdentifyGlobalLimit.Wait(ctx); err != nil {
    51  			return errors.Wrap(err, "can't wait for global limit")
    52  		}
    53  	}
    54  
    55  	return nil
    56  }
    57  
    58  // DefaultIdentity is used as the default identity when initializing a new
    59  // Gateway.
    60  var DefaultIdentity = IdentifyProperties{
    61  	OS:      runtime.GOOS,
    62  	Browser: "Arikawa",
    63  	Device:  "Arikawa",
    64  }
    65  
    66  // IdentifyData is the struct for a data that's sent over in an Identify
    67  // command.
    68  type IdentifyData struct {
    69  	Token      string             `json:"token"`
    70  	Properties IdentifyProperties `json:"properties"`
    71  
    72  	Compress       bool `json:"compress,omitempty"`        // true
    73  	LargeThreshold uint `json:"large_threshold,omitempty"` // 50
    74  
    75  	Shard *Shard `json:"shard,omitempty"` // [ shard_id, num_shards ]
    76  
    77  	Presence *UpdateStatusData `json:"presence,omitempty"`
    78  
    79  	Intents Intents `json:"intents,omitempty"`
    80  }
    81  
    82  // DefaultIdentifyData creates a default IdentifyData with the given token.
    83  func DefaultIdentifyData(token string) IdentifyData {
    84  	return IdentifyData{
    85  		Token:      token,
    86  		Properties: DefaultIdentity,
    87  		Presence:   DefaultPresence,
    88  
    89  		Compress:       true,
    90  		LargeThreshold: 50,
    91  	}
    92  }
    93  
    94  // SetShard is a helper function to set the shard configuration inside
    95  // IdentifyData.
    96  func (i *IdentifyData) SetShard(id, num int) {
    97  	if i.Shard == nil {
    98  		i.Shard = new(Shard)
    99  	}
   100  	i.Shard[0], i.Shard[1] = id, num
   101  }
   102  
   103  type IdentifyProperties struct {
   104  	// Required
   105  	OS      string `json:"os"`      // GOOS
   106  	Browser string `json:"browser"` // Arikawa
   107  	Device  string `json:"device"`  // Arikawa
   108  
   109  	// Optional
   110  	BrowserUserAgent string `json:"browser_user_agent,omitempty"`
   111  	BrowserVersion   string `json:"browser_version,omitempty"`
   112  	OSVersion        string `json:"os_version,omitempty"`
   113  	Referrer         string `json:"referrer,omitempty"`
   114  	ReferringDomain  string `json:"referring_domain,omitempty"`
   115  }
   116  
   117  // Shard is a type for two numbers that represent the Bot's shard configuration.
   118  // The first number is the shard's ID, which could be obtained through the
   119  // ShardID method. The second number is the total number of shards, which could
   120  // be obtained through the NumShards method.
   121  type Shard [2]int
   122  
   123  // DefaultShard returns the default shard configuration of 1 shard total, in
   124  // which the current shard ID is 0.
   125  var DefaultShard = &Shard{0, 1}
   126  
   127  // ShardID returns the current shard's ID. It uses the first number.
   128  func (s Shard) ShardID() int {
   129  	return s[0]
   130  }
   131  
   132  // NumShards returns the total number of shards. It uses the second number.
   133  func (s Shard) NumShards() int {
   134  	return s[1]
   135  }