Repository: nicklaw5/helix
Pull request #75 (2021-02-24 12:51:15)

Add GetChannelInformation endpoint
Added endpoint function for getting channel information, also cleared up some formatting and documentation.

coveralls: ## Pull Request Test Coverage Report for [Build 596073605](https://coveralls.io/builds/37410048)

* **8** of **10**   **(80.0%)**  changed or added relevant lines in **1** file are covered.
* No unchanged relevant lines lost coverage.
* Overall coverage decreased (**-0.1%**) to **88.138%**

---

|  Changes Missing Coverage | Covered Lines | Changed/Added Lines | % |
| :-----|--------------|--------|---: |
| [channels.go](https://coveralls.io/builds/37410048/source?filename=channels.go#L83) | 8 | 10 | 80.0%
<!-- | **Total:** | **8** | **10** | **80.0%** | -->


|  Totals | [![Coverage Status](https://coveralls.io/builds/37410048/badge)](https://coveralls.io/builds/37410048) |
| :-- | --: |
| Change from base [Build 542076608](https://coveralls.io/builds/36916087): |  -0.1% |
| Covered Lines: | 691 |
| Relevant Lines: | 784 |

---
##### 💛  - [Coveralls](https://coveralls.io)

nicklaw5: Thanks @codedninja. I'll take a look over the next day or so.

Patch:
diff --git a/ads.go b/ads.go
index da18cd7..11a3680 100644
--- a/ads.go
+++ b/ads.go
@@ -1,7 +1,9 @@
 package helix
 
+// AdLengthEnum ...
 type AdLengthEnum int
 
+// AdLen30 ...
 const (
 	_ AdLengthEnum = iota * 30
 	AdLen30
@@ -18,17 +20,19 @@ type StartCommercialParams struct {
 	Length        AdLengthEnum `query:"length"`
 }
 
+// AdDetails ...
 type AdDetails struct {
 	Length     AdLengthEnum `json:"length"`
 	Message    string       `json:"message"`
 	RetryAfter int          `json:"retry_after"`
 }
 
+// ManyAdDetails ...
 type ManyAdDetails struct {
 	AdDetails []AdDetails `json:"data"`
 }
 
-// StartCommercialResponse
+// StartCommercialResponse ...
 type StartCommercialResponse struct {
 	ResponseCommon
 	Data ManyAdDetails
diff --git a/bits.go b/bits.go
index 2738b9b..6b364b8 100644
--- a/bits.go
+++ b/bits.go
@@ -51,10 +51,12 @@ func (c *Client) GetBitsLeaderboard(params *BitsLeaderboardParams) (*BitsLeaderb
 	return bits, nil
 }
 
+// CheermotesParams ...
 type CheermotesParams struct {
 	BroadcasterID string `query:"broadcaster_id"` // optional
 }
 
+// TierImages ...
 type TierImages struct {
 	Image1   string `json:"1"`
 	Image1_5 string `json:"1.5"`
@@ -63,16 +65,19 @@ type TierImages struct {
 	Image4   string `json:"4"`
 }
 
+// TierImageTypes ...
 type TierImageTypes struct {
 	Animated TierImages `json:"animated"`
 	Static   TierImages `json:"static"`
 }
 
+// CheermoteTierImages ...
 type CheermoteTierImages struct {
 	Dark  TierImageTypes `json:"dark"`
 	Light TierImageTypes `json:"light"`
 }
 
+// CheermoteTiers ...
 type CheermoteTiers struct {
 	MinBits        uint                `json:"min_bits"`
 	ID             string              `json:"id"`
@@ -82,6 +87,7 @@ type CheermoteTiers struct {
 	ShowInBitsCard bool                `json:"show_in_bits_card"`
 }
 
+// Cheermotes ...
 type Cheermotes struct {
 	Prefix       string           `json:"prefix"`
 	Tiers        []CheermoteTiers `json:"tiers"`
@@ -91,15 +97,18 @@ type Cheermotes struct {
 	IsCharitable bool             `json:"is_charitable"`
 }
 
+// ManyCheermotes ...
 type ManyCheermotes struct {
 	Cheermotes []Cheermotes `json:"data"`
 }
 
+// CheermotesResponse ...
 type CheermotesResponse struct {
 	ResponseCommon
 	Data ManyCheermotes
 }
 
+// GetCheermotes ...
 func (c *Client) GetCheermotes(params *CheermotesParams) (*CheermotesResponse, error) {
 	resp, err := c.get("/bits/cheermotes", &ManyCheermotes{}, params)
 	if err != nil {
diff --git a/channels.go b/channels.go
index f9c4057..2f2cf6a 100644
--- a/channels.go
+++ b/channels.go
@@ -49,3 +49,43 @@ func (c *Client) SearchChannels(params *SearchChannelsParams) (*SearchChannelsRe
 
 	return channels, nil
 }
+
+// GetChannelInformationParams ...
+type GetChannelInformationParams struct {
+	BroadcasterID string `query:"broadcaster_id"`
+}
+
+// GetChannelInformationResponse ...
+type GetChannelInformationResponse struct {
+	ResponseCommon
+	Data ManyChannelInformation
+}
+
+// ManyChannelInformation ...
+type ManyChannelInformation struct {
+	Channels []ChannelInformation `json:"data"`
+}
+
+// ChannelInformation ...
+type ChannelInformation struct {
+	BroadcasterID         string `json:"broadcaster_id"`
+	BroadcasterName    string `json:"broadcaster_name"`
+	BroadcasterLanguage   string `json:"broadcaster_language"`
+	GameID string `json:"game_id"`
+	GameName   string `json:"game_name"`
+	Title      string `json:"title"`
+}
+
+// GetChannelInformation ...
+func (c *Client) GetChannelInformation(params *GetChannelInformationParams) (*GetChannelInformationResponse, error) {
+	resp, err := c.get("/channels", &ManyChannelInformation{}, params)
+	if err != nil {
+		return nil, err
+	}
+
+	channels := &GetChannelInformationResponse{}
+	resp.HydrateResponseCommon(&channels.ResponseCommon)
+	channels.Data.Channels = resp.Data.(*ManyChannelInformation).Channels
+
+	return channels, nil
+}
diff --git a/drops.go b/drops.go
index d787c7b..ca8f3ae 100644
--- a/drops.go
+++ b/drops.go
@@ -2,20 +2,20 @@ package helix
 
 // GetDropEntitlementsParams ...
 type GetDropEntitlementsParams struct {
-	ID string `query:"id"`
-	UserID        string `query:"user_id"`
-	GameID        string `query:"game_id"`
-	After         string `query:"after"`
-	First         int    `query:"first,20"` // Limit 100
+	ID     string `query:"id"`
+	UserID string `query:"user_id"`
+	GameID string `query:"game_id"`
+	After  string `query:"after"`
+	First  int    `query:"first,20"` // Limit 100
 }
 
 // Entitlement ...
 type Entitlement struct {
-	ID string `json:"id"`
-	BenefitID     string `json:"benefit_id"`
-	Timestamp     Time   `json:"timestamp"`
-	UserID        string `json:"user_id"`
-	GameID        string `json:"game_id"`
+	ID        string `json:"id"`
+	BenefitID string `json:"benefit_id"`
+	Timestamp Time   `json:"timestamp"`
+	UserID    string `json:"user_id"`
+	GameID    string `json:"game_id"`
 }
 
 // ManyEntitlements ...
diff --git a/entitlement_codes.go b/entitlement_codes.go
index 8e5edc0..55c9acc 100644
--- a/entitlement_codes.go
+++ b/entitlement_codes.go
@@ -38,7 +38,8 @@ type CodeResponse struct {
 	Data ManyCodes
 }
 
-/**
+/*
+GetEntitlementCodeStatus ...
 Per https://dev.twitch.tv/docs/api/reference#get-code-status
 Access is controlled via an app access token on the calling service. The client ID associated with the app access token must be approved by Twitch as part of a contracted arrangement.
 Callers with an app access token are authorized to redeem codes on behalf of any Twitch user account.
@@ -56,7 +57,8 @@ func (c *Client) GetEntitlementCodeStatus(params *CodesParams) (*CodeResponse, e
 	return codes, nil
 }
 
-/**
+/*
+RedeemEntitlementCode ...
 Per https://dev.twitch.tv/docs/api/reference/#redeem-code
 Access is controlled via an app access token on the calling service. The client ID associated with the app access token must be approved by Twitch.
 Callers with an app access token are authorized to redeem codes on behalf of any Twitch user account.
diff --git a/moderation.go b/moderation.go
index a506497..b8f7d55 100644
--- a/moderation.go
+++ b/moderation.go
@@ -21,7 +21,7 @@ type BannedUsersResponse struct {
 	Data ManyBans
 }
 
-// BannedUsersResponse
+// BannedUsersParams ...
 // BroadcasterID must match the auth tokens user_id
 type BannedUsersParams struct {
 	BroadcasterID string `query:"broadcaster_id"`
diff --git a/user_extensions.go b/user_extensions.go
index 4acdce1..84f2a9f 100644
--- a/user_extensions.go
+++ b/user_extensions.go
@@ -87,6 +87,7 @@ func (c *Client) GetUserActiveExtensions(params *UserActiveExtensionsParams) (*U
 	return userActiveExtensions, nil
 }
 
+// UpdateUserExtensionsPayload ...
 type UpdateUserExtensionsPayload struct {
 	Component map[string]UserActiveExtensionInfo `json:"component,omitempty"`
 	Overlay   map[string]UserActiveExtensionInfo `json:"overlay,omitempty"`


Test patch:
diff --git a/ads_test.go b/ads_test.go
index 823a514..0f51549 100644
--- a/ads_test.go
+++ b/ads_test.go
@@ -12,7 +12,7 @@ func TestClient_StartCommercial(t *testing.T) {
 		statusCode     int
 		options        *Options
 		count          int
-		broadcasterId  string
+		broadcasterID  string
 		adLength       AdLengthEnum
 		respBody       string
 		expectedErrMsg string
@@ -45,7 +45,7 @@ func TestClient_StartCommercial(t *testing.T) {
 		c := newMockClient(testCase.options, newMockHandler(testCase.statusCode, testCase.respBody, nil))
 
 		params := &StartCommercialParams{
-			BroadcasterID: testCase.broadcasterId,
+			BroadcasterID: testCase.broadcasterID,
 			Length:        testCase.adLength,
 		}
 
diff --git a/channels_test.go b/channels_test.go
index f37813e..775aa27 100644
--- a/channels_test.go
+++ b/channels_test.go
@@ -21,7 +21,7 @@ func TestSearchChannels(t *testing.T) {
 			2,
 			`{"data":[{"broadcaster_language":"en","display_name":"Ninja","game_id":"33214","id":"27833742640","is_live":false,"tag_ids":[],"thumbnail_url":"https://static-cdn.jtvnw.net/previews-ttv/live_user_ninja-{width}x{height}.jpg","title":"I have lost my voice D: | twitter.com/Ninja","started_at":"2018-03-06T15:07:45Z"},{"broadcaster_language":"en","display_name":"DrDisrespect","game_id":"33214","id":"27834185424","is_live":false,"tag_ids":[],"thumbnail_url":"https://static-cdn.jtvnw.net/previews-ttv/live_user_drdisrespectlive-{width}x{height}.jpg","title":"Turbo Treehouses || @DrDisRespect","started_at":"2018-03-06T16:05:00Z"}],"pagination":{"cursor":"eyJiIjpudWxsLCJhIjp7Ik9mZnNldCI6Mn19"}}`,
 			[]Channel{
-				Channel{
+				{
 					ID:               "27833742640",
 					GameID:           "33214",
 					BroadcasterLogin: "ninja",
@@ -32,7 +32,7 @@ func TestSearchChannels(t *testing.T) {
 					IsLive:           false,
 					TagIDs:           []string{},
 				},
-				Channel{
+				{
 					ID:               "27834185424",
 					GameID:           "33214",
 					BroadcasterLogin: "drdisrespect",
@@ -109,3 +109,89 @@ func TestSearchChannels(t *testing.T) {
 		}
 	}
 }
+
+func TestGetChannelInformation(t *testing.T) {
+	t.Parallel()
+
+	testCases := []struct {
+		statusCode    int
+		options       *Options
+		BroadcasterID string
+		respBody      string
+		parsed        []ChannelInformation
+	}{
+		{
+			http.StatusOK,
+			&Options{ClientID: "my-client-id"},
+			"44445592",
+			`{"data":[{"broadcaster_id":"44445592","broadcaster_login":"pokimane","broadcaster_name":"pokimane","broadcaster_language":"en","game_id":"509658","game_name":"Just Chatting","title":"See you Wednesday 8am for Among Us ^_^"}]}`,
+			[]ChannelInformation{
+				{
+					BroadcasterID:         "44445592",
+					BroadcasterName:    "pokimane",
+					BroadcasterLanguage:   "en",
+					GameID: "509658",
+					GameName:   "Just Chatting",
+					Title:      "See you Wednesday 8am for Among Us ^_^",
+				},
+			},
+		},
+		{
+			http.StatusBadRequest,
+			&Options{ClientID: "my-client-id"},
+			"9999999999999999999",
+			`{"error":"Bad Request","status":400,"message":"Invalid broadcasterID"}`,
+			[]ChannelInformation{},
+		},
+	}
+
+	for _, testCase := range testCases {
+		c := newMockClient(testCase.options, newMockHandler(testCase.statusCode, testCase.respBody, nil))
+
+		resp, err := c.GetChannelInformation(&GetChannelInformationParams{
+			BroadcasterID: testCase.BroadcasterID,
+		})
+		if err != nil {
+			t.Error(err)
+		}
+
+		// Test Bad Request Responses
+		if resp.StatusCode == http.StatusBadRequest {
+			broadcasterIDErrStr := "Invalid broadcasterID"
+			if resp.ErrorMessage != broadcasterIDErrStr {
+				t.Errorf("expected error message to be \"%s\", got \"%s\"", broadcasterIDErrStr, resp.ErrorMessage)
+				continue
+			}
+		}
+
+		if resp.StatusCode != testCase.statusCode {
+			t.Errorf("expected status code to be \"%d\", got \"%d\"", testCase.statusCode, resp.StatusCode)
+		}
+
+		for i, channel := range resp.Data.Channels {
+			if channel.BroadcasterID != testCase.parsed[i].BroadcasterID {
+				t.Errorf("Expected struct field BroadcasterID = %s, was %s", testCase.parsed[i].BroadcasterID, channel.BroadcasterID)
+			}
+
+			if channel.BroadcasterName != testCase.parsed[i].BroadcasterName {
+				t.Errorf("Expected struct field BroadcasterName = %s, was %s", testCase.parsed[i].BroadcasterName, channel.BroadcasterName)
+			}
+
+			if channel.BroadcasterLanguage != testCase.parsed[i].BroadcasterLanguage {
+				t.Errorf("Expected struct field BroadcasterLanguage = %s, was %s", testCase.parsed[i].BroadcasterLanguage, channel.BroadcasterLanguage)
+			}
+
+			if channel.GameID != testCase.parsed[i].GameID {
+				t.Errorf("Expected struct field GameID = %s, was %s", testCase.parsed[i].GameID, channel.GameID)
+			}
+
+			if channel.GameName != testCase.parsed[i].GameName {
+				t.Errorf("Expected struct field GameName = %s, was %s", testCase.parsed[i].GameName, channel.GameName)
+			}
+
+			if channel.Title != testCase.parsed[i].Title {
+				t.Errorf("Expected struct field Title = %s, was %s", testCase.parsed[i].Title, channel.Title)
+			}
+		}
+	}
+}
diff --git a/drops_test.go b/drops_test.go
index bb5a16e..6f97143 100644
--- a/drops_test.go
+++ b/drops_test.go
@@ -10,11 +10,11 @@ func TestGetDropsEntitlements(t *testing.T) {
 	t.Parallel()
 
 	testCases := []struct {
-		statusCode      int
-		options         *Options
-		gameID          string
-		respBody        string
-		expectedErrMsg  string
+		statusCode     int
+		options        *Options
+		gameID         string
+		respBody       string
+		expectedErrMsg string
 	}{
 		{
 			http.StatusUnauthorized,
diff --git a/entitlement_codes_test.go b/entitlement_codes_test.go
index 78ae4b7..fde0ea9 100644
--- a/entitlement_codes_test.go
+++ b/entitlement_codes_test.go
@@ -12,7 +12,7 @@ func TestClient_GetEntitlementCodeStatus(t *testing.T) {
 		statusCode int
 		options    *Options
 		count      int
-		userId     string
+		userID     string
 		codes      []string
 		respBody   string
 	}{
@@ -31,7 +31,7 @@ func TestClient_GetEntitlementCodeStatus(t *testing.T) {
 		c := newMockClient(testCase.options, newMockHandler(testCase.statusCode, testCase.respBody, nil))
 
 		params := &CodesParams{
-			UserID: testCase.userId,
+			UserID: testCase.userID,
 			Codes:  testCase.codes,
 		}
 
@@ -68,7 +68,7 @@ func TestClient_RedeemEntitlementCode(t *testing.T) {
 		statusCode int
 		options    *Options
 		count      int
-		userId     string
+		userID     string
 		codes      []string
 		respBody   string
 	}{
@@ -87,7 +87,7 @@ func TestClient_RedeemEntitlementCode(t *testing.T) {
 		c := newMockClient(testCase.options, newMockHandler(testCase.statusCode, testCase.respBody, nil))
 
 		params := &CodesParams{
-			UserID: testCase.userId,
+			UserID: testCase.userID,
 			Codes:  testCase.codes,
 		}
 
diff --git a/user_extension_test.go b/user_extension_test.go
index 6bd6d27..b7128e8 100644
--- a/user_extension_test.go
+++ b/user_extension_test.go
@@ -94,7 +94,7 @@ func TestUpdateUserExtensions(t *testing.T) {
 			&Options{ClientID: "my-client-id", UserAccessToken: "my-access-token"},
 			&UpdateUserExtensionsPayload{
 				Panel: map[string]UserActiveExtensionInfo{
-					"1": UserActiveExtensionInfo{
+					"1": {
 						Active: false,
 					},
 				},
diff --git a/webhooks_test.go b/webhooks_test.go
index da330a4..41c3251 100644
--- a/webhooks_test.go
+++ b/webhooks_test.go
@@ -124,7 +124,7 @@ func TestPostWebhookSubscriptions(t *testing.T) {
 }
 
 func newMockWebhookRequest(header string) *http.Request {
-	return &http.Request{Header: map[string][]string{"Link": []string{header}}}
+	return &http.Request{Header: map[string][]string{"Link": {header}}}
 }
 
 func TestGetWebhookTopicFromRequest(t *testing.T) {