-
Notifications
You must be signed in to change notification settings - Fork 90
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #183 from Mahcks/raids
Add raid support
- Loading branch information
Showing
4 changed files
with
279 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
# Raid Documentation | ||
|
||
## Start Raid | ||
|
||
This is an example of how to start a raid. | ||
|
||
```go | ||
client, err := helix.NewClient(&helix.Options{ | ||
ClientID: "your-client-id", | ||
}) | ||
if err != nil { | ||
// handle error | ||
} | ||
|
||
resp, err := client.StartRaid(&helix.StartRaidParams{ | ||
FromBroadcasterID: "22484632", | ||
ToBroadcasterID: "71092938" | ||
}) | ||
if err != nil { | ||
// handle error | ||
} | ||
|
||
fmt.Printf("%+v\n", resp) | ||
``` | ||
|
||
## Cancel Raid | ||
|
||
This is an example of how to cancel a raid. | ||
|
||
```go | ||
client, err := helix.NewClient(&helix.Options{ | ||
ClientID: "your-client-id", | ||
}) | ||
if err != nil { | ||
// handle error | ||
} | ||
|
||
resp, err := resp, err := client.CancelRaid(&helix.CancelRaidParams{ | ||
BroadcasterID: "22484632", | ||
}) | ||
if err != nil { | ||
// handle error | ||
} | ||
|
||
fmt.Printf("%+v\n", resp) | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
package helix | ||
|
||
// RaidResponse is the response from StartRaid | ||
type RaidResponse struct { | ||
ResponseCommon | ||
Data StartRaidResponse | ||
} | ||
|
||
// StartRaidParams are the parameters for StartRaid | ||
type StartRaidParams struct { | ||
FromBroadcasterID string `query:"from_broadcaster_id"` | ||
ToBroadcasterID string `query:"to_broadcaster_id"` | ||
} | ||
|
||
// StartRaidResponse is the response data in RaidResponse | ||
type StartRaidResponse struct { | ||
Data []RaidDetails `json:"data"` | ||
} | ||
|
||
// RaidDetails describes details of the ongoing raid | ||
type RaidDetails struct { | ||
CreatedAt Time `json:"created_at"` | ||
IsMature bool `json:"is_mature"` | ||
} | ||
|
||
// StartRaid raids another channel by sending the broadcaster’s viewers to the targeted channel. | ||
// When called, the Twitch UX pops up a window at the top of the chat room that identifies the number of viewers in the raid. | ||
// The raid occurs when the broadcaster clicks Raid Now or after the 90-second countdown expires. | ||
// Required scope: channel:manage:raids | ||
// Rate limit: 10 requests within a 10-minute window. | ||
func (c *Client) StartRaid(params *StartRaidParams) (*RaidResponse, error) { | ||
resp, err := c.post("/raids", &StartRaidResponse{}, params) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
raid := &RaidResponse{} | ||
resp.HydrateResponseCommon(&raid.ResponseCommon) | ||
|
||
return raid, nil | ||
} | ||
|
||
// CancelRaidResponse is the response from StartRaid | ||
type CancelRaidResponse struct { | ||
ResponseCommon | ||
} | ||
|
||
// CancelRaidParams are the parameters for CancelRaid | ||
type CancelRaidParams struct { | ||
BroadcasterID string `query:"broadcaster_id"` | ||
} | ||
|
||
// CancelRaid cancels a pending raid. | ||
// Required scope: channel:manage:raids | ||
// Rate limit: 10 requests within a 10-minute window. | ||
func (c *Client) CancelRaid(params *CancelRaidParams) (*CancelRaidResponse, error) { | ||
resp, err := c.delete("/raids", nil, params) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
canceledRaid := &CancelRaidResponse{} | ||
resp.HydrateResponseCommon(&canceledRaid.ResponseCommon) | ||
|
||
return canceledRaid, nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,165 @@ | ||
package helix | ||
|
||
import ( | ||
"context" | ||
"net/http" | ||
"testing" | ||
) | ||
|
||
func TestStartRaid(t *testing.T) { | ||
t.Parallel() | ||
|
||
testCases := []struct { | ||
statusCode int | ||
options *Options | ||
FromBroadcasterID string | ||
ToBroadcasterID string | ||
respBody string | ||
}{ | ||
{ | ||
http.StatusOK, | ||
&Options{ClientID: "my-client-id"}, | ||
"237509153", | ||
"237509153", | ||
`{"data":[{"created_at": "2022-02-18T07:20:50.52Z","is_mature": false}]}`, | ||
}, | ||
{ | ||
http.StatusBadRequest, | ||
&Options{ClientID: "my-client-id"}, | ||
"237509153", | ||
"237509153", | ||
`{"error":"Bad Request","status":400,"message":"The IDs in \"from_broadcaster_id\" and \"to_broadcaster_id\" cannot be the same ID."}`, | ||
}, | ||
} | ||
|
||
for _, testCase := range testCases { | ||
c := newMockClient(testCase.options, newMockHandler(testCase.statusCode, testCase.respBody, nil)) | ||
|
||
resp, err := c.StartRaid(&StartRaidParams{ | ||
FromBroadcasterID: testCase.FromBroadcasterID, | ||
ToBroadcasterID: testCase.ToBroadcasterID, | ||
}) | ||
if err != nil { | ||
t.Error(err) | ||
} | ||
|
||
if resp.StatusCode != testCase.statusCode { | ||
t.Errorf("expected status code to be %d, got %d", testCase.statusCode, resp.StatusCode) | ||
} | ||
|
||
if resp.StatusCode == http.StatusBadRequest { | ||
if resp.Error != "Bad Request" { | ||
t.Errorf("expected error to be %s, got %s", "Bad Request", resp.Error) | ||
} | ||
|
||
if resp.ErrorStatus != http.StatusBadRequest { | ||
t.Errorf("expected error status to be %d, got %d", http.StatusBadRequest, resp.ErrorStatus) | ||
} | ||
|
||
expectedErrMsg := "The IDs in \"from_broadcaster_id\" and \"to_broadcaster_id\" cannot be the same ID." | ||
if resp.ErrorMessage != expectedErrMsg { | ||
t.Errorf("expected error message to be %s, got %s", expectedErrMsg, resp.ErrorMessage) | ||
} | ||
|
||
continue | ||
} | ||
} | ||
|
||
// Test with HTTP Failure | ||
options := &Options{ | ||
ClientID: "my-client-id", | ||
HTTPClient: &badMockHTTPClient{ | ||
newMockHandler(0, "", nil), | ||
}, | ||
} | ||
c := &Client{ | ||
opts: options, | ||
ctx: context.Background(), | ||
} | ||
|
||
_, err := c.StartRaid(&StartRaidParams{}) | ||
if err == nil { | ||
t.Error("expected error but got nil") | ||
} | ||
|
||
if err.Error() != "Failed to execute API request: Oops, that's bad :(" { | ||
t.Error("expected error does match return error") | ||
} | ||
} | ||
|
||
func TestCancelRaid(t *testing.T) { | ||
t.Parallel() | ||
|
||
testCases := []struct { | ||
statusCode int | ||
options *Options | ||
BroadcasterID string | ||
respBody string | ||
}{ | ||
{ | ||
http.StatusNoContent, | ||
&Options{ClientID: "my-client-id"}, | ||
"237509153", | ||
"", | ||
}, | ||
{ | ||
http.StatusBadRequest, | ||
&Options{ClientID: "my-client-id"}, | ||
"237509153", | ||
`{"error":"Bad Request","status":400,"message":"The ID in the \"broadcaster_id query\" parameter is not valid."}`, | ||
}, | ||
} | ||
|
||
for _, testCase := range testCases { | ||
c := newMockClient(testCase.options, newMockHandler(testCase.statusCode, testCase.respBody, nil)) | ||
|
||
resp, err := c.CancelRaid(&CancelRaidParams{ | ||
BroadcasterID: testCase.BroadcasterID, | ||
}) | ||
if err != nil { | ||
t.Error(err) | ||
} | ||
|
||
if resp.StatusCode != testCase.statusCode { | ||
t.Errorf("expected status code to be %d, got %d", testCase.statusCode, resp.StatusCode) | ||
} | ||
|
||
if resp.StatusCode == http.StatusBadRequest { | ||
if resp.Error != "Bad Request" { | ||
t.Errorf("expected error to be %s, got %s", "Bad Request", resp.Error) | ||
} | ||
|
||
if resp.ErrorStatus != http.StatusBadRequest { | ||
t.Errorf("expected error status to be %d, got %d", http.StatusBadRequest, resp.ErrorStatus) | ||
} | ||
|
||
expectedErrMsg := "The ID in the \"broadcaster_id query\" parameter is not valid." | ||
if resp.ErrorMessage != expectedErrMsg { | ||
t.Errorf("expected error message to be %s, got %s", expectedErrMsg, resp.ErrorMessage) | ||
} | ||
|
||
continue | ||
} | ||
} | ||
|
||
// Test with HTTP Failure | ||
options := &Options{ | ||
ClientID: "my-client-id", | ||
HTTPClient: &badMockHTTPClient{ | ||
newMockHandler(0, "", nil), | ||
}, | ||
} | ||
c := &Client{ | ||
opts: options, | ||
ctx: context.Background(), | ||
} | ||
|
||
_, err := c.CancelRaid(&CancelRaidParams{}) | ||
if err == nil { | ||
t.Error("expected error but got nil") | ||
} | ||
|
||
if err.Error() != "Failed to execute API request: Oops, that's bad :(" { | ||
t.Error("expected error does match return error") | ||
} | ||
} |