diff --git a/LICENSE b/LICENSE index 7d38c09..142ac7b 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2018 RumbleFrog +Copyright (c) 2018-2026 RumbleFrog & Top.gg Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/bots.go b/bots.go index 75ef7cf..efea0f1 100644 --- a/bots.go +++ b/bots.go @@ -3,29 +3,41 @@ package dbl import ( "bytes" "encoding/json" + "fmt" "strconv" "strings" "time" ) +type Reviews struct { + // The project's average review score out of 5 + Score float64 `json:"averageScore"` + + // The project's review count + Count int `json:"count"` +} + type Bot struct { - // The id of the bot + // The Top.gg id of the bot ID string `json:"id"` + // The Discord id of the bot + ClientID string `json:"clientid"` + // The username of the bot Username string `json:"username"` // The discriminator of the bot - Discriminator string `json:"discriminator"` + Discriminator string `json:"-"` - // The avatar hash of the bot's avatar (may be empty) + // The bot's avatar url Avatar string `json:"avatar"` // The cdn hash of the bot's avatar if the bot has none - DefAvatar string `json:"defAvatar"` + DefAvatar string `json:"-"` // The library of the bot - Library string `json:"lib"` + Library string `json:"-"` // The prefix of the bot Prefix string `json:"prefix"` @@ -42,7 +54,7 @@ type Bot struct { // The website url of the bot (may be empty) Website string `json:"website"` - // The support server invite code of the bot (may be empty) + // The support server url of the bot (may be empty) Support string `json:"support"` // The link to the github repo of the bot (may be empty) @@ -54,32 +66,32 @@ type Bot struct { // The custom bot invite url of the bot (may be empty) Invite string `json:"invite"` - // The date when the bot was approved + // The date when the bot was submitted Date time.Time `json:"date"` - // The certified status of the bot - CertifiedBot bool `json:"certifiedBot"` - - // The vanity url of the bot (deprecated) (may be empty) + // The vanity url of the bot (may be empty) Vanity string `json:"vanity"` - // The monthly amount of upvotes the bot has (undocumented) + // The monthly amount of votes the bot has MonthlyPoints int `json:"monthlyPoints"` - // The amount of upvotes the bot has + // The amount of votes the bot has Points int `json:"points"` // The GuildID for the donate bot (undocumented) (may be empty) - DonateBotGuildID string `json:"donatebotguildid"` + DonateBotGuildID string `json:"-"` - // The amount of servers the bot is in (undocumented) + // The amount of servers the bot is in ServerCount int `json:"server_count"` // Server affiliation ("Servers this bot is in" field) (undocumented) - GuildAffiliation []string `json:"guilds"` + GuildAffiliation []string `json:"-"` // The amount of servers the bot is in per shard. Always present but can be empty (undocumented) - Shards []int `json:"shards"` + Shards []int `json:"-"` + + // The bot's reviews + Review *Reviews `json:"reviews"` } type GetBotsPayload struct { @@ -94,7 +106,7 @@ type GetBotsPayload struct { // Field search filter Search map[string]string - // The field to sort by. Prefix with "-" to reverse the order + // The field to sort by descending, valid field names are "id", "date", and "monthlyPoints". Sort string // A list of fields to show @@ -135,6 +147,9 @@ type checkResponse struct { } type BotStatsPayload struct { + // The amount of servers the bot is in, must not be zero. + ServerCount int `json:"server_count"` + // The amount of servers the bot is in per shard. Shards []int `json:"shards"` @@ -149,39 +164,38 @@ type BotStatsPayload struct { // // Use nil if no option is passed func (c *Client) GetBots(filter *GetBotsPayload) (*GetBotsResult, error) { - if c.token == "" { - return nil, ErrRequireAuthentication - } - - if !c.limiter.Allow() { - return nil, ErrLocalRatelimit - } - req, err := c.createRequest("GET", "bots", nil) - if filter != nil { + if err != nil { + return nil, err + } else if filter != nil { q := req.URL.Query() - if filter.Limit != 0 { - q.Add("limit", strconv.Itoa(filter.Limit)) - } + if filter.Limit > 0 { + if filter.Limit > 500 { + filter.Limit = 500 + } - if filter.Offset != 0 { - q.Add("offset", strconv.Itoa(filter.Offset)) + q.Add("limit", strconv.Itoa(filter.Limit)) + } else { + q.Add("limit", "50") } - if len(filter.Search) != 0 { - tStack := make([]string, 0) - - for f, v := range filter.Search { - tStack = append(tStack, f+": "+v) + if filter.Offset >= 0 { + if filter.Offset > 499 { + filter.Offset = 499 } - q.Add("search", strings.Join(tStack, " ")) + q.Add("offset", strconv.Itoa(filter.Offset)) } if filter.Sort != "" { - q.Add("sort", filter.Sort) + switch filter.Sort { + case "id", "date", "monthlyPoints": + q.Add("sort", filter.Sort) + default: + return nil, ErrInvalidRequest + } } if len(filter.Fields) != 0 { @@ -216,14 +230,6 @@ func (c *Client) GetBots(filter *GetBotsPayload) (*GetBotsResult, error) { // Information about a specific bot func (c *Client) GetBot(botID string) (*Bot, error) { - if c.token == "" { - return nil, ErrRequireAuthentication - } - - if !c.limiter.Allow() { - return nil, ErrLocalRatelimit - } - req, err := c.createRequest("GET", "bots/"+botID, nil) if err != nil { @@ -253,26 +259,26 @@ func (c *Client) GetBot(botID string) (*Bot, error) { return bot, nil } -// Use this endpoint to see who have upvoted your bot +// Fetches your project's recent 100 unique voters // -// Requires authentication -// -// IF YOU HAVE OVER 1000 VOTES PER MONTH YOU HAVE TO USE THE WEBHOOKS AND CAN NOT USE THIS -func (c *Client) GetVotes(botID string) ([]*User, error) { - if c.token == "" { - return nil, ErrRequireAuthentication - } - - if !c.limiter.Allow() { - return nil, ErrLocalRatelimit +// # Requires authentication +func (c *Client) GetVotes(page int) ([]*User, error) { + if page <= 0 { + return nil, ErrInvalidRequest } - req, err := c.createRequest("GET", "bots/"+botID+"/votes", nil) + req, err := c.createRequest("GET", fmt.Sprintf("bots/%s/votes", c.id), nil) if err != nil { return nil, err } + q := req.URL.Query() + + q.Add("page", strconv.Itoa(page)) + + req.URL.RawQuery = q.Encode() + res, err := c.httpClient.Do(req) if err != nil { @@ -287,7 +293,7 @@ func (c *Client) GetVotes(botID string) ([]*User, error) { users := make([]*User, 0) - err = json.Unmarshal(body, users) + err = json.Unmarshal(body, &users) if err != nil { return nil, err @@ -296,19 +302,13 @@ func (c *Client) GetVotes(botID string) ([]*User, error) { return users, nil } -// Use this endpoint to see who have upvoted your bot in the past 24 hours. It is safe to use this even if you have over 1k votes. +// Use this endpoint to see who have upvoted for your project in the past 12 hours. It is safe to use this even if you have over 1k votes. // -// Requires authentication -func (c *Client) HasUserVoted(botID, userID string) (bool, error) { - if c.token == "" { - return false, ErrRequireAuthentication - } - - if !c.limiter.Allow() { - return false, ErrLocalRatelimit - } - - req, err := c.createRequest("GET", "bots/"+botID+"/check", nil) +// # Requires authentication +// +// The _botID argument is no longer used. +func (c *Client) HasUserVoted(_botID, userID string) (bool, error) { + req, err := c.createRequest("GET", "bots/check", nil) if err != nil { return false, err @@ -344,16 +344,10 @@ func (c *Client) HasUserVoted(botID, userID string) (bool, error) { } // Information about a specific bot's stats -func (c *Client) GetBotStats(botID string) (*BotStats, error) { - if c.token == "" { - return nil, ErrRequireAuthentication - } - - if !c.limiter.Allow() { - return nil, ErrLocalRatelimit - } - - req, err := c.createRequest("GET", "bots/"+botID+"/stats", nil) +// +// The _botID argument is no longer used. +func (c *Client) GetBotStats(_botID string) (*BotStats, error) { + req, err := c.createRequest("GET", "bots/stats", nil) if err != nil { return nil, err @@ -382,35 +376,31 @@ func (c *Client) GetBotStats(botID string) (*BotStats, error) { return botStats, nil } -// Post your bot's stats +// Post your bot's server count // -// Requires authentication +// # Requires authentication // -// If your bot is unsharded, pass in server count as the only item in the slice -func (c *Client) PostBotStats(botID string, payload *BotStatsPayload) error { - if c.token == "" { - return ErrRequireAuthentication +// The _botID argument is no longer used. +func (c *Client) PostBotStats(_botID string, payload *BotStatsPayload) error { + if payload.ServerCount <= 0 { + return ErrInvalidRequest } - if !c.limiter.Allow() { - return ErrLocalRatelimit - } - - encoded, err := json.Marshal(payload) + encoded, err := json.Marshal(&BotStats{ + ServerCount: payload.ServerCount, + Shards: []int{}, + }) if err != nil { return err } - req, err := c.createRequest("POST", "bots/"+botID+"/stats", bytes.NewBuffer(encoded)) + req, err := c.createRequest("POST", "bots/stats", bytes.NewBuffer(encoded)) if err != nil { return err } - req.Header.Set("Authorization", c.token) - req.Header.Set("Content-Type", "application/json") - res, err := c.httpClient.Do(req) if err != nil { diff --git a/bots_test.go b/bots_test.go index 924db3d..b8b0181 100644 --- a/bots_test.go +++ b/bots_test.go @@ -1,6 +1,7 @@ package dbl import ( + "log" "os" "testing" @@ -13,7 +14,7 @@ const ( ) func TestBots(t *testing.T) { - client, err := NewClient(os.Getenv("apikey")) + client, err := NewClient(os.Getenv("TOPGG_TOKEN")) assert.Nil(t, err, "Client should be created w/o error") @@ -21,6 +22,10 @@ func TestBots(t *testing.T) { Limit: fetchLimit, }) + if err != nil { + log.Fatal(err) + } + assert.Nil(t, err, "Request should be successful (API depended)") assert.Equal(t, fetchLimit, len(bots.Results), "Results array size should match request limit") @@ -29,7 +34,7 @@ func TestBots(t *testing.T) { } func TestBot(t *testing.T) { - client, err := NewClient(os.Getenv("apikey")) + client, err := NewClient(os.Getenv("TOPGG_TOKEN")) assert.Nil(t, err, "Client should be created w/o error") diff --git a/client.go b/client.go index 3e2782b..f55a207 100644 --- a/client.go +++ b/client.go @@ -1,8 +1,11 @@ package dbl import ( + "encoding/base64" + "encoding/json" "fmt" "net/http" + "strings" "sync" "time" @@ -32,22 +35,44 @@ type Client struct { limiter *rate.Limiter httpClient HTTPClient token string + id string +} + +type tokenStructure struct { + Id string `json:"id"` } // NewClient returns a new *Client after applying the options provided. func NewClient(token string, options ...OptionFunc) (*Client, error) { + tokenSections := strings.Split(token, ".") + + if len(tokenSections) != 3 { + return nil, ErrRequireAuthentication + } + + decodedTokenSection, err := base64.RawURLEncoding.DecodeString(tokenSections[1]) + + if err != nil { + return nil, ErrRequireAuthentication + } + + innerTokenStructure := &tokenStructure{} + + if err = json.Unmarshal(decodedTokenSection, innerTokenStructure); err != nil { + return nil, ErrRequireAuthentication + } + client := &Client{ limiter: rate.NewLimiter(1, 60), httpClient: &http.Client{Timeout: defaultTimeout}, token: token, + id: innerTokenStructure.Id, } for _, optionFunc := range options { if optionFunc == nil { return nil, fmt.Errorf("invalid nil dbl.Client option func") - } - - if err := optionFunc(client); err != nil { + } else if err := optionFunc(client); err != nil { return nil, fmt.Errorf("error running dbl.Client option func: %w", err) } } diff --git a/client_test.go b/client_test.go index 5ae6495..60b0bf4 100644 --- a/client_test.go +++ b/client_test.go @@ -3,8 +3,11 @@ package dbl import ( "log" "net/http" + "os" "testing" "time" + + "github.com/stretchr/testify/assert" ) func TestNewClient(t *testing.T) { @@ -12,14 +15,54 @@ func TestNewClient(t *testing.T) { httpClient := &http.Client{} - _, err := NewClient( - "token", + client, err := NewClient( + os.Getenv("TOPGG_TOKEN"), HTTPClientOption(httpClient), // Setting a custom HTTP client. Default is *http.Client with default timeout. TimeoutOption(clientTimeout), // Setting timeout option. Default is 3 seconds ) + if err != nil { - log.Fatalf("Error creating new Discord Bot List client: %s", err) + log.Fatalf("Error creating new Top.gg client: %s", err) } - // ... + _, err = client.GetBotStats("") + + assert.Nil(t, err, "GetBotStats should succeed") + + err = client.PostBotStats("", &BotStatsPayload{ + ServerCount: 2, + }) + + assert.Nil(t, err, "PostBotStats should succeed") + + time.Sleep(1 * time.Second) + _, err = client.GetBot("264811613708746752") + + assert.Nil(t, err, "GetBot should succeed") + + getBotsPayload := GetBotsPayload{ + Limit: 50, + Offset: 0, + Sort: "id", + } + + time.Sleep(1 * time.Second) + _, err = client.GetBots(&getBotsPayload) + + assert.Nil(t, err, "GetBots should succeed") + + time.Sleep(1 * time.Second) + _, err = client.GetVotes(1) + + assert.Nil(t, err, "GetVotes should succeed") + + time.Sleep(1 * time.Second) + _, err = client.HasUserVoted("", "8226924471638491136") + + assert.Nil(t, err, "HasUserVoted should succeed") + + time.Sleep(1 * time.Second) + _, err = client.IsMultiplierActive() + + assert.Nil(t, err, "IsMultiplierActive should succeed") } diff --git a/errors.go b/errors.go index 00b853c..8235d95 100644 --- a/errors.go +++ b/errors.go @@ -3,9 +3,10 @@ package dbl import "errors" var ( - ErrRequestFailed = errors.New("Remote request failed with non 200 status code") - ErrLocalRatelimit = errors.New("Exceeded local rate limit") - ErrRemoteRatelimit = errors.New("Exceeded remote rate limit") - ErrUnauthorizedRequest = errors.New("Unauthorized request") - ErrRequireAuthentication = errors.New("Endpoint requires valid token") + ErrRequestFailed = errors.New("remote request failed with non 200 status code") + ErrLocalRatelimit = errors.New("exceeded local rate limit") + ErrRemoteRatelimit = errors.New("exceeded remote rate limit") + ErrUnauthorizedRequest = errors.New("unauthorized request") + ErrRequireAuthentication = errors.New("endpoint requires valid token") + ErrInvalidRequest = errors.New("invalid attempted request") ) diff --git a/users.go b/users.go index a5d32e2..072da29 100644 --- a/users.go +++ b/users.go @@ -1,8 +1,6 @@ package dbl -import ( - "encoding/json" -) +import "encoding/json" type User struct { // The id of the user @@ -14,7 +12,7 @@ type User struct { // The discriminator of the user Discriminator string `json:"discriminator"` - // The avatar hash of the user's avatar (may be empty) + // The avatar url of the user (may be empty) Avatar string `json:"avatar"` // The cdn hash of the user's avatar if the user has none @@ -26,6 +24,7 @@ type User struct { // The banner image url of the user (may be empty) Banner string `json:"banner"` + // The user's socials Social *Social `json:"social"` // The custom hex color of the user (may be empty) @@ -43,7 +42,7 @@ type User struct { // The website moderator status of the user WebsiteModerator bool `json:"webMod"` - // The admin status of the user + // The admin status of the user Admin bool `json:"admin"` } @@ -54,7 +53,7 @@ type Social struct { // The reddit username of the user (may be empty) Reddit string `json:"reddit"` - // The twitter username of the user (may be empty) + // The twitter username of the user (may be empty) Twitter string `json:"twitter"` // The instagram username of the user (may be empty) @@ -64,7 +63,7 @@ type Social struct { Github string `json:"github"` } -// Information about a particular user +// [Deprecated] Information about a particular user func (c *Client) GetUser(UserID string) (*User, error) { if c.token == "" { return nil, ErrRequireAuthentication diff --git a/users_test.go b/users_test.go deleted file mode 100644 index 023ea2d..0000000 --- a/users_test.go +++ /dev/null @@ -1,24 +0,0 @@ -package dbl - -import ( - "os" - "testing" - - "github.com/stretchr/testify/assert" -) - -const ( - testUserID = "105122038586286080" -) - -func TestUsers(t *testing.T) { - client, err := NewClient(os.Getenv("apikey")) - - assert.Nil(t, err, "Client should be created w/o error") - - user, err := client.GetUser(testUserID) - - assert.Nil(t, err, "Unable to get user data") - - assert.Equal(t, testUserID, user.ID, "Request & response user ID should match") -} diff --git a/util.go b/util.go index 01d5c72..a2bf44b 100644 --- a/util.go +++ b/util.go @@ -3,7 +3,6 @@ package dbl import ( "encoding/json" "io" - "io/ioutil" "net/http" ) @@ -14,15 +13,18 @@ type ratelimitResponse struct { func (c *Client) readBody(res *http.Response) ([]byte, error) { defer res.Body.Close() - if res.StatusCode == 401 { + switch res.StatusCode { + case 400: + return nil, ErrInvalidRequest + case 401: return nil, ErrUnauthorizedRequest - } - - if res.StatusCode != 200 { + case 200: + break + default: return nil, ErrRequestFailed } - body, err := ioutil.ReadAll(res.Body) + body, err := io.ReadAll(res.Body) if err != nil { return nil, err @@ -48,13 +50,22 @@ func (c *Client) readBody(res *http.Response) ([]byte, error) { } func (c *Client) createRequest(method, endpoint string, body io.Reader) (*http.Request, error) { + if c.token == "" { + return nil, ErrRequireAuthentication + } + + if !c.limiter.Allow() { + return nil, ErrLocalRatelimit + } + req, err := http.NewRequest(method, BaseURL+endpoint, body) if err != nil { return nil, err } - req.Header.Set("Authorization", c.token) + req.Header.Set("Authorization", "Bearer "+c.token) + req.Header.Set("Content-Type", "application/json") return req, nil } diff --git a/voter.go b/voter.go new file mode 100644 index 0000000..71aec03 --- /dev/null +++ b/voter.go @@ -0,0 +1,12 @@ +package dbl + +type Voter struct { + // The id of the voter + ID string `json:"id"` + + // The username of the voter + Username string `json:"username"` + + // The voter's avatar url + Avatar string `json:"avatar"` +} diff --git a/webhook.go b/webhook.go index fc01bf4..e6ee21b 100644 --- a/webhook.go +++ b/webhook.go @@ -2,7 +2,7 @@ package dbl import ( "encoding/json" - "io/ioutil" + "io" "net/http" "net/url" ) @@ -80,7 +80,7 @@ func (wl *WebhookListener) handlePayload(w http.ResponseWriter, r *http.Request) return } - body, err := ioutil.ReadAll(r.Body) + body, err := io.ReadAll(r.Body) if err != nil { return @@ -95,7 +95,7 @@ func (wl *WebhookListener) handlePayload(w http.ResponseWriter, r *http.Request) m, err := url.ParseQuery(p.Query) if err != nil { - return + m = nil } w.WriteHeader(http.StatusNoContent) diff --git a/webhook_test.go b/webhook_test.go index 2647c9c..f272ea1 100644 --- a/webhook_test.go +++ b/webhook_test.go @@ -2,6 +2,7 @@ package dbl import ( "bytes" + "fmt" "net/http" "net/http/httptest" "testing" @@ -15,7 +16,9 @@ const ( var ( testPayload = []byte(`{"bot":"441751906428256277","user":"105122038586286080","type":"upvote","isWeekend":false,"query":""}`) - testListener = NewListener(testToken, func(p *WebhookPayload) {}) + testListener = NewListener(testToken, func(p *WebhookPayload) { + fmt.Printf("A user with the ID of %s has voted us on Top.gg!", p.User) + }) ) func TestHookMethod(t *testing.T) { diff --git a/weekend.go b/weekend.go index c4cd515..2627a85 100644 --- a/weekend.go +++ b/weekend.go @@ -10,10 +10,6 @@ type weekendResponse struct { // Check if the multiplier is live for the weekend func (c *Client) IsMultiplierActive() (bool, error) { - if c.token == "" { - return false, ErrRequireAuthentication - } - req, err := c.createRequest("GET", "weekend", nil) if err != nil { diff --git a/weekend_test.go b/weekend_test.go index 2950f5e..3c4eac7 100644 --- a/weekend_test.go +++ b/weekend_test.go @@ -1,13 +1,14 @@ package dbl import ( + "os" "testing" "github.com/stretchr/testify/assert" ) func TestWeekend(t *testing.T) { - client, err := NewClient("Unauthenticated request") + client, err := NewClient(os.Getenv("TOPGG_TOKEN")) assert.Nil(t, err, "Client should be created w/o error") diff --git a/widget_general.go b/widget_general.go deleted file mode 100644 index b29afb9..0000000 --- a/widget_general.go +++ /dev/null @@ -1,46 +0,0 @@ -package dbl - -import ( - "net/url" - "strconv" -) - -type Extension int - -const ( - SVG Extension = iota - PNG -) - -type Widget interface { - BotID() Widget - Generate() string - Extension() Widget -} - -type WidgetData struct { - botID string - values url.Values - extension Extension -} - -func (w *WidgetData) setValue(key string, value int64) { - w.values.Add(key, strconv.FormatInt(value, 16)) -} - -func (e Extension) Ext() string { - switch e { - case SVG: - { - return ".svg" - } - case PNG: - { - return ".png" - } - default: - { - return ".svg" - } - } -} diff --git a/widget_large.go b/widget_large.go deleted file mode 100644 index 2552fe6..0000000 --- a/widget_large.go +++ /dev/null @@ -1,80 +0,0 @@ -package dbl - -import ( - "net/url" -) - -type LargeWidget struct { - Widget - data WidgetData -} - -func NewLargeWidget() *LargeWidget { - return &LargeWidget{ - data: WidgetData{ - values: url.Values(make(map[string][]string)), - }, - } -} - -func (w *LargeWidget) BotID(id string) *LargeWidget { - w.data.botID = id - - return w -} - -func (w *LargeWidget) Extension(extension Extension) *LargeWidget { - w.data.extension = extension - - return w -} - -func (w *LargeWidget) TopColor(color int64) *LargeWidget { - w.data.setValue("topcolor", color) - - return w -} - -func (w *LargeWidget) MiddleColor(color int64) *LargeWidget { - w.data.setValue("middlecolor", color) - - return w -} - -func (w *LargeWidget) UsernameColor(color int64) *LargeWidget { - w.data.setValue("usernamecolor", color) - - return w -} - -func (w *LargeWidget) CertifiedColor(color int64) *LargeWidget { - w.data.setValue("certifiedcolor", color) - - return w -} - -func (w *LargeWidget) DataColor(color int64) *LargeWidget { - w.data.setValue("datacolor", color) - - return w -} - -func (w *LargeWidget) LabelColor(color int64) *LargeWidget { - w.data.setValue("labelcolor", color) - - return w -} - -func (w *LargeWidget) HighlightColor(color int64) *LargeWidget { - w.data.setValue("highlightcolor", color) - - return w -} - -func (w *LargeWidget) Generate() string { - u, _ := url.Parse(BaseURL + "widgets/" + w.data.botID + w.data.extension.Ext()) - - u.RawQuery = w.data.values.Encode() - - return u.String() -} diff --git a/widget_large_test.go b/widget_large_test.go deleted file mode 100644 index 1233f38..0000000 --- a/widget_large_test.go +++ /dev/null @@ -1,32 +0,0 @@ -package dbl - -import ( - "testing" - - "github.com/stretchr/testify/assert" -) - -var ( - expectedLargeWidget = BaseURL + "widgets/574652751745777665.png?certifiedcolor=343434&topcolor=fffff" - expectedLargeWidgetNoExt = BaseURL + "widgets/574652751745777665.svg?datacolor=309839" -) - -func TestWidgetLarge(t *testing.T) { - w := NewLargeWidget(). - BotID(testBotID). - Extension(PNG). - TopColor(0xfffff). - CertifiedColor(0x343434). - Generate() - - assert.Equal(t, expectedLargeWidget, w) -} - -func TestWidgetLargeNoExt(t *testing.T) { - w := NewLargeWidget(). - BotID(testBotID). - DataColor(0x309839). - Generate() - - assert.Equal(t, expectedLargeWidgetNoExt, w) -} diff --git a/widget_small.go b/widget_small.go deleted file mode 100644 index dc6c5f4..0000000 --- a/widget_small.go +++ /dev/null @@ -1,107 +0,0 @@ -package dbl - -import "net/url" - -type WidgetType int - -const ( - WidgetStatus WidgetType = iota - WidgetUpvotes - WidgetServers - WidgetLib -) - -func (t WidgetType) String() string { - switch t { - case WidgetStatus: - { - return "status" - } - case WidgetUpvotes: - { - return "upvotes" - } - case WidgetServers: - { - return "servers" - } - case WidgetLib: - { - return "lib" - } - default: - { - return "status" - } - } -} - -type SmallWidget struct { - Widget - data WidgetData - wType WidgetType -} - -func NewSmallWidget() *SmallWidget { - return &SmallWidget{ - data: WidgetData{ - values: url.Values(make(map[string][]string)), - }, - } -} - -func (w *SmallWidget) BotID(id string) *SmallWidget { - w.data.botID = id - - return w -} - -func (w *SmallWidget) Extension(extension Extension) *SmallWidget { - w.data.extension = extension - - return w -} - -func (w *SmallWidget) WidgetType(wType WidgetType) *SmallWidget { - w.wType = wType - - return w -} - -func (w *SmallWidget) AvatarBackground(color int64) *SmallWidget { - w.data.setValue("avatarbg", color) - - return w -} - -func (w *SmallWidget) LeftColor(color int64) *SmallWidget { - w.data.setValue("leftcolor", color) - - return w -} - -func (w *SmallWidget) RightColor(color int64) *SmallWidget { - w.data.setValue("rightcolor", color) - - return w -} - -func (w *SmallWidget) LeftTextColor(color int64) *SmallWidget { - w.data.setValue("lefttextcolor", color) - - return w -} - -func (w *SmallWidget) RightTextColor(color int64) *SmallWidget { - w.data.setValue("righttextcolor", color) - - return w -} - -func (w *SmallWidget) Generate() string { - u, _ := url.Parse(BaseURL + "widgets/" + w.wType.String() + "/" + w.data.botID + w.data.extension.Ext()) - - u.RawQuery = w.data.values.Encode() - - return u.String() -} diff --git a/widget_small_test.go b/widget_small_test.go deleted file mode 100644 index 8f997f6..0000000 --- a/widget_small_test.go +++ /dev/null @@ -1,33 +0,0 @@ -package dbl - -import ( - "testing" - - "github.com/stretchr/testify/assert" -) - -var ( - expectedSmallWidget = BaseURL + "widgets/servers/574652751745777665.svg?leftcolor=555798&righttextcolor=f12350" - expectedSmallWidgetNoType = BaseURL + "widgets/status/574652751745777665.svg?avatarbg=987230&lefttextcolor=123890" -) - -func TestWidgetSmall(t *testing.T) { - w := NewSmallWidget(). - BotID(testBotID). - WidgetType(WidgetServers). - LeftColor(0x555798). - RightTextColor(0xf12350). - Generate() - - assert.Equal(t, expectedSmallWidget, w) -} - -func TestWidgetSmallNoType(t *testing.T) { - w := NewSmallWidget(). - BotID(testBotID). - AvatarBackground(0x987230). - LeftTextColor(0x123890). - Generate() - - assert.Equal(t, expectedSmallWidgetNoType, w) -}