Repository: nicklaw5/helix
Pull request #83 (2021-04-19 22:01:44)

Add Block User features
 - Get User Block List
 - Block User
 - Unblock User

Ref: #74



Patch:
diff --git a/README.md b/README.md
index b8d862b..461d205 100644
--- a/README.md
+++ b/README.md
@@ -77,9 +77,9 @@ looking for the Twitch API docs, see the [Twitch Developer website](https://dev.
 - [x] Get Users Follows
 - [ ] Create User Follows
 - [ ] Delete User Follows
-- [ ] Get User Block List
-- [ ] Block User
-- [ ] UnBlock User
+- [x] Get User Block List
+- [x] Block User
+- [x] UnBlock User
 - [ ] Get User Extensions
 - [ ] Get User Active Extensions
 - [ ] Update User Extensions
diff --git a/docs/users_docs.md b/docs/users_docs.md
index 5b0bfc5..d3a95cc 100644
--- a/docs/users_docs.md
+++ b/docs/users_docs.md
@@ -67,3 +67,71 @@ if err != nil {
 
 fmt.Printf("%+v\n", resp)
 ```
+
+## Get User Block List
+
+This is an example of how to get users blocked
+
+```
+client, err := helix.NewClient(&helix.Options{
+    ClientID: "your-client-id",
+})
+if err != nil {
+    // handle error
+}
+
+resp, err := client.GetUsersBlocked(&helix.UsersBlockedParams{
+    BroadcasterID: "145328278",
+})
+if err != nil {
+    // handle error
+}
+
+fmt.Printf("%+v\n", resp)
+```
+
+## Block User
+
+This is an example of how to block user
+
+```
+client, err := helix.NewClient(&helix.Options{
+    ClientID: "your-client-id",
+})
+if err != nil {
+    // handle error
+}
+
+resp, err := client.BlockUser(&helix.BlockUserParams{
+    TargetUserID:  "677636701",
+    SourceContext: "chat",
+    Reason:        "spam",
+})
+if err != nil {
+    // handle error
+}
+
+fmt.Printf("%+v\n", resp)
+```
+
+## Unblock User
+
+This is an example of how to unblock user
+
+```
+client, err := helix.NewClient(&helix.Options{
+    ClientID: "your-client-id",
+})
+if err != nil {
+    // handle error
+}
+
+resp, err := client.UnblockUser(&helix.UnblockUserParams{
+    TargetUserID: "677636701",
+})
+if err != nil {
+    // handle error
+}
+
+fmt.Printf("%+v\n", resp)
+```
diff --git a/users.go b/users.go
index 38058d2..f78bf12 100644
--- a/users.go
+++ b/users.go
@@ -122,3 +122,94 @@ func (c *Client) GetUsersFollows(params *UsersFollowsParams) (*UsersFollowsRespo
 
 	return users, nil
 }
+
+// UserBlocked ...
+type UserBlocked struct {
+	UserID    string `json:"user_id"`
+	UserLogin string `json:"user_login"`
+	DisplayName  string `json:"display_name"`
+}
+
+// ManyUsersBlocked ...
+type ManyUsersBlocked struct {
+	Users      []UserBlocked `json:"data"`
+	Pagination Pagination   `json:"pagination"`
+}
+
+// UsersBlockedResponse ...
+type UsersBlockedResponse struct {
+	ResponseCommon
+	Data ManyUsersBlocked
+}
+
+// UsersBlockedParams ...
+type UsersBlockedParams struct {
+	BroadcasterID string `query:"broadcaster_id"`
+	After         string `query:"after"`
+	First         int    `query:"first,20"` // Limit 100
+}
+
+// GetUsersBlocked : Gets a specified user’s block list.
+//
+// Required scope: user:read:blocked_users
+func (c *Client) GetUsersBlocked(params *UsersBlockedParams) (*UsersBlockedResponse, error) {
+	resp, err := c.get("/users/blocks", &ManyUsersBlocked{}, params)
+	if err != nil {
+		return nil, err
+	}
+
+	users := &UsersBlockedResponse{}
+	resp.HydrateResponseCommon(&users.ResponseCommon)
+	users.Data.Users = resp.Data.(*ManyUsersBlocked).Users
+	users.Data.Pagination = resp.Data.(*ManyUsersBlocked).Pagination
+
+	return users, nil
+}
+
+// BlockUserResponse ...
+type BlockUserResponse struct {
+	ResponseCommon
+}
+
+// BlockUserParams ...
+type BlockUserParams struct {
+	TargetUserID  string `query:"target_user_id"`
+	SourceContext string `query:"source_context"` // Valid values: "chat", "whisper"
+	Reason        string `query:"reason"`         // Valid values: "spam", "harassment", "other"
+}
+
+// BlockUser : Blocks the specified user on behalf of the authenticated user.
+//
+// Required scope: user:manage:blocked_users
+func (c *Client) BlockUser(params *BlockUserParams) (*BlockUserResponse, error) {
+	resp, err := c.put("/users/blocks", nil, params)
+	if err != nil {
+		return nil, err
+	}
+
+	block := &BlockUserResponse{}
+	resp.HydrateResponseCommon(&block.ResponseCommon)
+
+	return block, nil
+}
+
+// UnblockUserParams ...
+type UnblockUserParams struct {
+	TargetUserID string `query:"target_user_id"`
+}
+
+// UnblockUser : Unblocks the specified user on behalf of the authenticated user.
+//
+// Required scope: user:manage:blocked_users
+func (c *Client) UnblockUser(params *UnblockUserParams) (*BlockUserResponse, error) {
+	resp, err := c.delete("/users/blocks", nil, params)
+	if err != nil {
+		return nil, err
+	}
+
+	block := &BlockUserResponse{}
+	resp.HydrateResponseCommon(&block.ResponseCommon)
+
+	return block, nil
+}
+


Test patch:
diff --git a/users_test.go b/users_test.go
index 925cef5..d56ba5e 100644
--- a/users_test.go
+++ b/users_test.go
@@ -205,3 +205,207 @@ func TestGetUsersFollows(t *testing.T) {
 		}
 	}
 }
+
+func TestGetUsersBlocked(t *testing.T) {
+	t.Parallel()
+
+	testCases := []struct {
+		statusCode    int
+		options       *Options
+		BroadcasterID string
+		First         int
+		respBody      string
+	}{
+		{
+			http.StatusBadRequest,
+			&Options{ClientID: "my-client-id"},
+			"",
+			1,
+			`{"error":"Bad Request","status":400,"message":"Missing required parameter \"broadcaster_id\""}`,
+		},
+		{
+			http.StatusOK,
+			&Options{ClientID: "my-client-id"},
+			"23161357",
+			1,
+			`{"data":[{"user_id":"199340135","user_login":"jlarkyzus","display_name":"JLArkyzus"}],"pagination":{"cursor":"xxx"}}`,
+		},
+	}
+
+	for _, testCase := range testCases {
+		c := newMockClient(testCase.options, newMockHandler(testCase.statusCode, testCase.respBody, nil))
+
+		resp, err := c.GetUsersBlocked(&UsersBlockedParams{
+			First:         testCase.First,
+			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 := "Missing required parameter \"broadcaster_id\""
+			if resp.ErrorMessage != expectedErrMsg {
+				t.Errorf("expected error message to be \"%s\", got \"%s\"", expectedErrMsg, resp.ErrorMessage)
+			}
+
+			continue
+		}
+
+		if len(resp.Data.Users) != testCase.First {
+			t.Errorf("expected result length to be \"%d\", got \"%d\"", testCase.First, len(resp.Data.Users))
+		}
+
+		userID := "199340135"
+		if resp.Data.Users[0].UserID != userID {
+			t.Errorf("expected user id to be \"%s\", got \"%s\"", userID, resp.Data.Users[0].UserID)
+		}
+
+		userLogin := "jlarkyzus"
+		if resp.Data.Users[0].UserLogin != userLogin {
+			t.Errorf("expected user id to be \"%s\", got \"%s\"", userLogin, resp.Data.Users[0].UserLogin)
+		}
+
+		displayName := "JLArkyzus"
+		if resp.Data.Users[0].DisplayName != displayName {
+			t.Errorf("expected user id to be \"%s\", got \"%s\"", displayName, resp.Data.Users[0].DisplayName)
+		}
+
+		cursor := "xxx"
+		if resp.Data.Pagination.Cursor != cursor {
+			t.Errorf("expected cursor to be \"%s\", got \"%s\"", cursor, resp.Data.Pagination.Cursor)
+		}
+	}
+}
+
+func TestBlockUser(t *testing.T) {
+	t.Parallel()
+
+	testCases := []struct {
+		statusCode int
+		options    *Options
+		Params     *BlockUserParams
+		respBody   string
+	}{
+		{
+			http.StatusBadRequest,
+			&Options{ClientID: "my-client-id"},
+			&BlockUserParams{
+				TargetUserID:  "199340135",
+				SourceContext: "twitter",
+				Reason:        "spam",
+			},
+			`{"error":"Bad Request","status":400,"message":"The parameter \"source_context\" was malformed: value must be one of \"chat\", \"whisper\", \"\""}`,
+		},
+		{
+			http.StatusOK,
+			&Options{ClientID: "my-client-id"},
+			&BlockUserParams{
+				TargetUserID:  "199340135",
+				SourceContext: "chat",
+				Reason:        "spam",
+			},
+			``,
+		},
+	}
+
+	for _, testCase := range testCases {
+		c := newMockClient(testCase.options, newMockHandler(testCase.statusCode, testCase.respBody, nil))
+
+		resp, err := c.BlockUser(testCase.Params)
+		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 parameter \"source_context\" was malformed: value must be one of \"chat\", \"whisper\", \"\""
+			if resp.ErrorMessage != expectedErrMsg {
+				t.Errorf("expected error message to be \"%s\", got \"%s\"", expectedErrMsg, resp.ErrorMessage)
+			}
+
+			continue
+		}
+	}
+}
+
+func TestUnblockUser(t *testing.T) {
+	t.Parallel()
+
+	testCases := []struct {
+		statusCode int
+		options    *Options
+		Params     *UnblockUserParams
+		respBody   string
+	}{
+		{
+			http.StatusBadRequest,
+			&Options{ClientID: "my-client-id"},
+			&UnblockUserParams{
+				TargetUserID:  "",
+			},
+			`{"error":"Bad Request","status":400,"message":"Missing required parameter \"target_user_id\""}`,
+		},
+		{
+			http.StatusOK,
+			&Options{ClientID: "my-client-id"},
+			&UnblockUserParams{
+				TargetUserID:  "199340135",
+			},
+			``,
+		},
+	}
+
+	for _, testCase := range testCases {
+		c := newMockClient(testCase.options, newMockHandler(testCase.statusCode, testCase.respBody, nil))
+
+		resp, err := c.UnblockUser(testCase.Params)
+		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 := "Missing required parameter \"target_user_id\""
+			if resp.ErrorMessage != expectedErrMsg {
+				t.Errorf("expected error message to be \"%s\", got \"%s\"", expectedErrMsg, resp.ErrorMessage)
+			}
+
+			continue
+		}
+	}
+}