Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ Wrapper for the raider.io API written in Go

### Include module in your go.mod
```
include github.com/tmaffia/raiderio v0.3.0
include github.com/tmaffia/raiderio v0.3.1
```

### Get a Character Profile
Expand Down
1 change: 1 addition & 0 deletions character.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ type Character struct {
ActiveRole string `json:"active_spec_role"`
Gender string `json:"gender"`
Faction string `json:"faction"`
Spec string `json:"spec"`
AchievementPoints int64 `json:"achievement_points"`
HonorableKills int64 `json:"honorable_kills"`
ThumbnailUrl string `json:"thumbnail_url"`
Expand Down
30 changes: 28 additions & 2 deletions client.go
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ func (c *Client) GetGuild(ctx context.Context, gq *GuildQuery) (*Guild, error) {
// GetRaids retrieves a list of raids from the Raider.IO API
// It returns an error if the API returns a non-200 status code, or if the
// response body cannot be read or mapped to the Raids struct
// Takes an Expansion enum as a parameter
// Takes an Expansion enum as a parameter, in addition to context.Context
func (c *Client) GetRaids(ctx context.Context, e expansion.Expansion) (*Raids, error) {
reqUrl := c.ApiUrl + "/raiding/static-data?expansion_id=" + fmt.Sprintf("%d", e)
body, err := c.getAPIResponse(ctx, reqUrl)
Expand All @@ -106,7 +106,7 @@ func (c *Client) GetRaids(ctx context.Context, e expansion.Expansion) (*Raids, e
// GetRaidRankings retrieves a list of raid rankings from the Raider.IO API
// It returns an error if the API returns a non-200 status code, or if the
// response body cannot be read or mapped to the RaidRankings struct
// Takes a RaidQuery struct as a parameter
// Takes a RaidQuery struct as a parameter, in addition to context.Context
func (c *Client) GetRaidRankings(ctx context.Context, rq *RaidQuery) (*RaidRankings, error) {
err := validateRaidRankingsQuery(rq)
if err != nil {
Expand Down Expand Up @@ -141,3 +141,29 @@ func (c *Client) GetRaidRankings(ctx context.Context, rq *RaidQuery) (*RaidRanki

return &rankings, nil
}

// GetGuildBossKill returns a guild's first kill of a given boss
// Takes a context.Context object to facilitate timeout, and a GuildBossKillQuery
// GuildBossKillQuery has only required fields for this request
// returns a BossKill object
func (c *Client) GetGuildBossKill(ctx context.Context, q *GuildBossKillQuery) (*BossKill, error) {
err := validateGuildBossKillQuery(q)
if err != nil {
return nil, err
}
reqUrl := c.ApiUrl + "/guilds/boss-kill?raid=" + q.RaidSlug +
"&difficulty=" + string(q.Difficulty) + "&region=" + q.Region.Slug +
"&realm=" + q.Realm + "&guild=" + q.GuildName + "&boss=" + q.BossSlug

body, err := c.getAPIResponse(ctx, reqUrl)
if err != nil {
return nil, err
}

k, err := unmarshalGuildBossKill(body)
if err != nil {
return nil, err
}

return k, nil
}
106 changes: 97 additions & 9 deletions client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ func TestGetCharacterProfile(t *testing.T) {
ctx := defaultCtx
var cancel context.CancelFunc
if tc.timeout {
ctx, cancel = context.WithTimeout(defaultCtx, time.Millisecond*10)
ctx, cancel = context.WithTimeout(defaultCtx, time.Millisecond*1)
defer cancel()
}

Expand Down Expand Up @@ -91,7 +91,7 @@ func TestGetCharacterWGear(t *testing.T) {
ctx := defaultCtx
var cancel context.CancelFunc
if tc.timeout {
ctx, cancel = context.WithTimeout(ctx, time.Millisecond*10)
ctx, cancel = context.WithTimeout(ctx, time.Millisecond*1)
defer cancel()
}

Expand Down Expand Up @@ -153,7 +153,7 @@ func TestGetGuild(t *testing.T) {
ctx := defaultCtx
var cancel context.CancelFunc
if tc.timeout {
ctx, cancel = context.WithTimeout(ctx, time.Millisecond*10)
ctx, cancel = context.WithTimeout(ctx, time.Millisecond*1)
defer cancel()
}

Expand Down Expand Up @@ -241,14 +241,15 @@ func TestGetGuildWRaidRankings(t *testing.T) {
{region: region.US, realm: "illidan", name: "warpath",
raidName: "aberrus-the-shadowed-crucible", expectedRank: 158},
{timeout: true, region: region.US, realm: "illidan", name: "warpath",
raidName: "aberrus-the-shadowed-crucible", expectedErrMsg: "raiderio api request timeout"},
raidName: "aberrus-the-shadowed-crucible",
expectedErrMsg: "raiderio api request timeout"},
}

for _, tc := range testCases {
ctx := defaultCtx
var cancel context.CancelFunc
if tc.timeout {
ctx, cancel = context.WithTimeout(ctx, time.Millisecond*10)
ctx, cancel = context.WithTimeout(ctx, time.Millisecond*1)
defer cancel()
}

Expand All @@ -274,12 +275,90 @@ func TestGetGuildWRaidRankings(t *testing.T) {
}
}

func TestGetGuildBossKill(t *testing.T) {
testCases := []struct {
region *region.Region
realm string
guildName string
raidSlug string
bossSlug string
difficulty raiderio.RaidDifficulty
expectedDefeatedAt string
expectedCharacterName string
expectedErrMsg string
timeout bool
}{
{region: region.US, realm: "illidan", guildName: "warpath",
raidSlug: "vault-of-the-incarnates", bossSlug: "terros",
difficulty: raiderio.MythicRaid, expectedCharacterName: "Drbananaphd"},
{region: nil, difficulty: raiderio.MythicRaid, realm: "illidan",
guildName: "warpath", raidSlug: "vault-of-the-incarnates",
bossSlug: "terros", expectedErrMsg: "invalid region"},
{region: region.US, difficulty: raiderio.MythicRaid,
realm: "invalid-realm", guildName: "warpath", raidSlug: "vault-of-the-incarnates",
bossSlug: "terros", expectedErrMsg: "invalid realm"},
{region: region.US, difficulty: raiderio.MythicRaid,
guildName: "warpath", raidSlug: "vault-of-the-incarnates",
bossSlug: "terros", expectedErrMsg: "invalid realm"},
{region: region.US, difficulty: raiderio.MythicRaid, realm: "illidan",
guildName: "impossible-guild_name", raidSlug: "vault-of-the-incarnates",
bossSlug: "terros", expectedErrMsg: "guild not found"},
{region: region.US, difficulty: raiderio.MythicRaid, realm: "illidan",
raidSlug: "vault-of-the-incarnates", bossSlug: "terros",
expectedErrMsg: "invalid guild name"},
{region: region.US, difficulty: raiderio.MythicRaid, realm: "illidan",
guildName: "warpath", raidSlug: "invalid-raid-slug", bossSlug: "terros",
expectedErrMsg: "invalid raid"},
{region: region.US, difficulty: raiderio.MythicRaid, realm: "illidan",
guildName: "warpath", bossSlug: "terros",
expectedErrMsg: "invalid raid name"},
{region: region.US, difficulty: raiderio.MythicRaid, realm: "illidan",
guildName: "warpath", raidSlug: "vault-of-the-incarnates",
bossSlug: "invalid-boss-slug", expectedErrMsg: "invalid boss"},
{region: region.US, difficulty: raiderio.MythicRaid, realm: "illidan",
guildName: "warpath", raidSlug: "vault-of-the-incarnates",
expectedErrMsg: "invalid boss"},
{region: region.US, realm: "illidan", guildName: "warpath",
raidSlug: "vault-of-the-incarnates", bossSlug: "terros",
expectedErrMsg: "invalid raid difficulty"},
{timeout: true, region: region.US, realm: "illidan", guildName: "warpath",
raidSlug: "vault-of-the-incarnates", bossSlug: "terros",
difficulty: raiderio.MythicRaid,
expectedErrMsg: "raiderio api request timeout"},
}

for _, tc := range testCases {
ctx := defaultCtx
var cancel context.CancelFunc
if tc.timeout {
ctx, cancel = context.WithTimeout(ctx, time.Millisecond*1)
defer cancel()
}

k, err := c.GetGuildBossKill(ctx, &raiderio.GuildBossKillQuery{
Region: tc.region,
Realm: tc.realm,
GuildName: tc.guildName,
RaidSlug: tc.raidSlug,
BossSlug: tc.bossSlug,
Difficulty: tc.difficulty,
})

if err != nil && err.Error() != tc.expectedErrMsg {
t.Fatalf("error message got: %v, expected: %v", err.Error(), tc.expectedErrMsg)
}

if err == nil && !killIncludesCharacter(k, tc.expectedCharacterName) {
t.Fatalf("boss kill character name expected: %v", tc.expectedCharacterName)
}
}
}

func TestGetRaids(t *testing.T) {
testCases := []struct {
timeout bool
expansion expansion.Expansion
raidName string
raidDifficulty string
expectedRaidName string
expectedErrMsg string
}{
Expand All @@ -292,7 +371,7 @@ func TestGetRaids(t *testing.T) {
ctx := defaultCtx
var cancel context.CancelFunc
if tc.timeout {
ctx, cancel = context.WithTimeout(ctx, time.Millisecond*10)
ctx, cancel = context.WithTimeout(ctx, time.Millisecond*1)
defer cancel()
}

Expand All @@ -312,7 +391,6 @@ func TestGetRaids(t *testing.T) {
}

func TestGetRaidRankings(t *testing.T) {
c := raiderio.NewClient()
testCases := []struct {
timeout bool
slug string
Expand Down Expand Up @@ -344,7 +422,7 @@ func TestGetRaidRankings(t *testing.T) {
ctx := defaultCtx
var cancel context.CancelFunc
if tc.timeout {
ctx, cancel = context.WithTimeout(ctx, time.Millisecond*10)
ctx, cancel = context.WithTimeout(ctx, time.Millisecond*1)
defer cancel()
}

Expand Down Expand Up @@ -372,3 +450,13 @@ func TestGetRaidRankings(t *testing.T) {
}
}
}

// Tests if character is a part of the particular boss kill
func killIncludesCharacter(k *raiderio.BossKill, c string) bool {
for _, v := range k.Roster {
if v.Name == c {
return true
}
}
return false
}
10 changes: 10 additions & 0 deletions errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ var (
ErrUnsupportedExpac = errors.New("unsupported expansion")
ErrLimitOutOfBounds = errors.New("limit must be a positive int")
ErrPageOutOfBounds = errors.New("page must be a positive int")
ErrInvalidBoss = errors.New("invalid boss")
ErrInvalidQuery = errors.New("invalid query")
ErrApiTimeout = errors.New("raiderio api request timeout")
ErrUnexpected = errors.New("unexpected error")
)
Expand All @@ -34,6 +36,14 @@ func wrapApiError(responseBody *apiErrorResponse) error {
return ErrInvalidRealm
}

if strings.Contains(responseBody.Message, "Failed to find raid") {
return ErrInvalidRaid
}

if strings.Contains(responseBody.Message, "Failed to find boss") {
return ErrInvalidBoss
}

if strings.Contains(responseBody.Message, "Could not find requested character") {
return ErrCharacterNotFound
}
Expand Down
Loading