github.com/diamondburned/arikawa@v1.3.14/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  // Identity is used as the default identity when initializing a new Gateway.
    13  var Identity = IdentifyProperties{
    14  	OS:      runtime.GOOS,
    15  	Browser: "Arikawa",
    16  	Device:  "Arikawa",
    17  }
    18  
    19  // Presence is used as the default presence when initializing a new Gateway.
    20  var Presence *UpdateStatusData
    21  
    22  type IdentifyProperties struct {
    23  	// Required
    24  	OS      string `json:"os"`      // GOOS
    25  	Browser string `json:"browser"` // Arikawa
    26  	Device  string `json:"device"`  // Arikawa
    27  
    28  	// Optional
    29  	BrowserUserAgent string `json:"browser_user_agent,omitempty"`
    30  	BrowserVersion   string `json:"browser_version,omitempty"`
    31  	OsVersion        string `json:"os_version,omitempty"`
    32  	Referrer         string `json:"referrer,omitempty"`
    33  	ReferringDomain  string `json:"referring_domain,omitempty"`
    34  }
    35  
    36  type IdentifyData struct {
    37  	Token      string             `json:"token"`
    38  	Properties IdentifyProperties `json:"properties"`
    39  
    40  	Compress           bool `json:"compress,omitempty"`        // true
    41  	LargeThreshold     uint `json:"large_threshold,omitempty"` // 50
    42  	GuildSubscriptions bool `json:"guild_subscriptions"`       // true
    43  
    44  	Shard *Shard `json:"shard,omitempty"` // [ shard_id, num_shards ]
    45  
    46  	Presence *UpdateStatusData `json:"presence,omitempty"`
    47  
    48  	Intents Intents `json:"intents,omitempty"`
    49  }
    50  
    51  func (i *IdentifyData) SetShard(id, num int) {
    52  	if i.Shard == nil {
    53  		i.Shard = new(Shard)
    54  	}
    55  	i.Shard[0], i.Shard[1] = id, num
    56  }
    57  
    58  // Intents for the new Discord API feature, documented at
    59  // https://discordapp.com/developers/docs/topics/gateway#gateway-intents.
    60  type Intents uint32
    61  
    62  const (
    63  	IntentGuilds Intents = 1 << iota
    64  	IntentGuildMembers
    65  	IntentGuildBans
    66  	IntentGuildEmojis
    67  	IntentGuildIntegrations
    68  	IntentGuildWebhooks
    69  	IntentGuildInvites
    70  	IntentGuildVoiceStates
    71  	IntentGuildPresences
    72  	IntentGuildMessages
    73  	IntentGuildMessageReactions
    74  	IntentGuildMessageTyping
    75  	IntentDirectMessages
    76  	IntentDirectMessageReactions
    77  	IntentDirectMessageTyping
    78  )
    79  
    80  type Identifier struct {
    81  	IdentifyData
    82  
    83  	IdentifyShortLimit  *rate.Limiter `json:"-"`
    84  	IdentifyGlobalLimit *rate.Limiter `json:"-"`
    85  }
    86  
    87  func DefaultIdentifier(token string) *Identifier {
    88  	return NewIdentifier(IdentifyData{
    89  		Token:      token,
    90  		Properties: Identity,
    91  		Shard:      DefaultShard(),
    92  		Presence:   Presence,
    93  
    94  		Compress:           true,
    95  		LargeThreshold:     50,
    96  		GuildSubscriptions: true,
    97  	})
    98  }
    99  
   100  func NewIdentifier(data IdentifyData) *Identifier {
   101  	return &Identifier{
   102  		IdentifyData:        data,
   103  		IdentifyShortLimit:  rate.NewLimiter(rate.Every(5*time.Second), 1),
   104  		IdentifyGlobalLimit: rate.NewLimiter(rate.Every(24*time.Hour), 1000),
   105  	}
   106  }
   107  
   108  func (i *Identifier) Wait(ctx context.Context) error {
   109  	if err := i.IdentifyShortLimit.Wait(ctx); err != nil {
   110  		return errors.Wrap(err, "can't wait for short limit")
   111  	}
   112  	if err := i.IdentifyGlobalLimit.Wait(ctx); err != nil {
   113  		return errors.Wrap(err, "can't wait for global limit")
   114  	}
   115  	return nil
   116  }