Repository: nicklaw5/helix
Pull request #162 (2022-12-23 22:15:08)

Update Custom Rewards
Adds ability to update custom rewards


Patch:
diff --git a/channels_points.go b/channels_points.go
index b4831a3..d866505 100644
--- a/channels_points.go
+++ b/channels_points.go
@@ -6,7 +6,25 @@ type ChannelCustomRewardsParams struct {
 	Cost                              int    `json:"cost"`
 	Prompt                            string `json:"prompt"`
 	IsEnabled                         bool   `json:"is_enabled"`
-	BackgroundColor                   string `json:"background_color"`
+	BackgroundColor                   string `json:"background_color,omitempty"`
+	IsUserInputRequired               bool   `json:"is_user_input_required"`
+	IsMaxPerStreamEnabled             bool   `json:"is_max_per_stream_enabled"`
+	MaxPerStream                      int    `json:"max_per_stream"`
+	IsMaxPerUserPerStreamEnabled      bool   `json:"is_max_per_user_per_stream_enabled"`
+	MaxPerUserPerStream               int    `json:"max_per_user_per_stream"`
+	IsGlobalCooldownEnabled           bool   `json:"is_global_cooldown_enabled"`
+	GlobalCooldownSeconds             int    `json:"global_cooldown_seconds"`
+	ShouldRedemptionsSkipRequestQueue bool   `json:"should_redemptions_skip_request_queue"`
+}
+
+type UpdateChannelCustomRewardsParams struct {
+	ID                                string `query:"id"`
+	BroadcasterID                     string `query:"broadcaster_id"`
+	Title                             string `json:"title"`
+	Cost                              int    `json:"cost"`
+	Prompt                            string `json:"prompt"`
+	IsEnabled                         bool   `json:"is_enabled"`
+	BackgroundColor                   string `json:"background_color,omitempty"`
 	IsUserInputRequired               bool   `json:"is_user_input_required"`
 	IsMaxPerStreamEnabled             bool   `json:"is_max_per_stream_enabled"`
 	MaxPerStream                      int    `json:"max_per_stream"`
@@ -41,6 +59,7 @@ type ChannelCustomReward struct {
 	Prompt                            string                      `json:"prompt"`
 	Cost                              int                         `json:"cost"`
 	Image                             RewardImage                 `json:"image"`
+	BackgroundColor                   string                      `json:"background_color"`
 	DefaultImage                      RewardImage                 `json:"default_image"`
 	IsEnabled                         bool                        `json:"is_enabled"`
 	IsUserInputRequired               bool                        `json:"is_user_input_required"`
@@ -100,6 +119,21 @@ func (c *Client) CreateCustomReward(params *ChannelCustomRewardsParams) (*Channe
 	return reward, nil
 }
 
+// UpdateCustomReward : Update a Custom Reward on a channel.
+// Required scope: channel:manage:redemptions
+func (c *Client) UpdateCustomReward(params *UpdateChannelCustomRewardsParams) (*ChannelCustomRewardResponse, error) {
+	resp, err := c.patchAsJSON("/channel_points/custom_rewards", &ManyChannelCustomRewards{}, params)
+	if err != nil {
+		return nil, err
+	}
+
+	reward := &ChannelCustomRewardResponse{}
+	resp.HydrateResponseCommon(&reward.ResponseCommon)
+	reward.Data.ChannelCustomRewards = resp.Data.(*ManyChannelCustomRewards).ChannelCustomRewards
+
+	return reward, nil
+}
+
 // DeleteCustomRewards : Deletes a Custom Rewards on a channel
 // Required scope: channel:manage:redemptions
 func (c *Client) DeleteCustomRewards(params *DeleteCustomRewardsParams) (*DeleteCustomRewardsResponse, error) {
diff --git a/docs/channels_points_docs.md b/docs/channels_points_docs.md
index bf2311d..2caba3b 100644
--- a/docs/channels_points_docs.md
+++ b/docs/channels_points_docs.md
@@ -24,6 +24,31 @@ if err != nil {
 fmt.Printf("%+v\n", resp)
 ```
 
+## Update Custom Rewards
+
+This is an example of how to update a custom reward.
+
+```go
+client, err := helix.NewClient(&helix.Options{
+    ClientID: "your-client-id",
+})
+if err != nil {
+    // handle error
+}
+
+resp, err := client.UpdateCustomReward(&helix.UpdateChannelCustomRewardsParams{
+    ID            : "6741db51-bc4e-4f0e-b96b-d79eafe227f3",
+    BroadcasterID : "145328278",
+    Title         : "game analysis 1v1",
+    Cost          : 50000,
+})
+if err != nil {
+    // handle error
+}
+
+fmt.Printf("%+v\n", resp)
+```
+
 ## Delete Custom Rewards
 
 This is an example of how to delete a custom rewards.


Test patch:
diff --git a/channels_points_test.go b/channels_points_test.go
index 8a66f3e..e5d53f0 100644
--- a/channels_points_test.go
+++ b/channels_points_test.go
@@ -75,6 +75,77 @@ func TestCreateCustomReward(t *testing.T) {
 	}
 }
 
+func TestUpdateCustomReward(t *testing.T) {
+	t.Parallel()
+
+	testCases := []struct {
+		statusCode int
+		options    *Options
+		params     *UpdateChannelCustomRewardsParams
+		respBody   string
+	}{
+		{
+			http.StatusOK,
+			&Options{ClientID: "my-client-id"},
+			&UpdateChannelCustomRewardsParams{
+				ID:            "123",
+				BroadcasterID: "145328278",
+				Title:         "game analysis 1v1",
+				Cost:          50000,
+			},
+			`{"data": [{"broadcaster_name": "torpedo09","broadcaster_login": "torpedo09","broadcaster_id": "145328278","id": "afaa7e34-6b17-49f0-a19a-d1e76eaaf673","image": null,"background_color": "#00E5CB","is_enabled": true,"cost": 50000,"title": "game analysis 1v1","prompt": "","is_user_input_required": false,"max_per_stream_setting": {"is_enabled": false,"max_per_stream": 0},"max_per_user_per_stream_setting": {"is_enabled": false,"max_per_user_per_stream": 0},"global_cooldown_setting": {"is_enabled": false,"global_cooldown_seconds": 0},"is_paused": false,"is_in_stock": true,"default_image": {"url_1x": "https://static-cdn.jtvnw.net/custom-reward-images/default-1.png","url_2x": "https://static-cdn.jtvnw.net/custom-reward-images/default-2.png","url_4x": "https://static-cdn.jtvnw.net/custom-reward-images/default-4.png"},"should_redemptions_skip_request_queue": false,"redemptions_redeemed_current_stream": null,"cooldown_expires_at": null}]}`,
+		},
+		{
+			http.StatusBadRequest,
+			&Options{ClientID: "my-client-id"},
+			&UpdateChannelCustomRewardsParams{},
+			`{"error":"Bad Request","status":400,"message":"Missing required parameter \"id\""}`,
+		},
+	}
+
+	for _, testCase := range testCases {
+		c := newMockClient(testCase.options, newMockHandler(testCase.statusCode, testCase.respBody, nil))
+
+		resp, err := c.UpdateCustomReward(testCase.params)
+		if err != nil {
+			t.Error(err)
+		}
+
+		// Test Bad Request Responses
+		if resp.StatusCode == http.StatusBadRequest {
+			firstErrStr := "Missing required parameter \"id\""
+			if resp.ErrorMessage != firstErrStr {
+				t.Errorf("expected error message to be \"%s\", got \"%s\"", firstErrStr, resp.ErrorMessage)
+			}
+			continue
+		}
+
+		if resp.StatusCode != testCase.statusCode {
+			t.Errorf("expected status code to be \"%d\", got \"%d\"", testCase.statusCode, resp.StatusCode)
+		}
+	}
+
+	// Test with HTTP Failure
+	options := &Options{
+		ClientID: "my-client-id",
+		HTTPClient: &badMockHTTPClient{
+			newMockHandler(0, "", nil),
+		},
+	}
+	c := &Client{
+		opts: options,
+	}
+
+	_, err := c.UpdateCustomReward(&UpdateChannelCustomRewardsParams{})
+	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 TestDeleteCustomRewards(t *testing.T) {
 	t.Parallel()