diff --git a/social/error.go b/social/error.go index c2e82a2b..034fd0c7 100644 --- a/social/error.go +++ b/social/error.go @@ -11,9 +11,10 @@ import ( ) const ( - socialCodeFriendListFull = 1028 // Observed when the People list limit would be exceeded. - socialCodeRestricted = 1011 // Observed for forbidden relationship operations. - socialCodeRestrictedPrivacy = 1049 // Observed for target-user privacy restrictions. + socialCodeFriendListFull = 1028 // Observed when the People list limit would be exceeded. + socialCodeRestricted = 1011 // Observed for forbidden relationship operations. + socialCodeRestrictedPrivacy = 1049 // Observed for target-user privacy restrictions. + socialCodeBulkOperationLimit = 1050 // Observed when a bulk relationship request contains too many users. ) var ( @@ -23,6 +24,9 @@ var ( ErrFriendListFull = errors.New("xsapi/social: friend list full") // ErrFriendRestricted matches privacy, enforcement, or relationship restriction responses. ErrFriendRestricted = errors.New("xsapi/social: friend restricted") + // ErrBulkOperationLimit matches responses indicating a bulk relationship + // request contains more users than the service accepts. + ErrBulkOperationLimit = errors.New("xsapi/social: bulk operation limit") ) // ResponseError carries error details returned by the Xbox Live Social and @@ -71,6 +75,8 @@ func (e *ResponseError) Is(target error) bool { return e.Code == socialCodeFriendListFull case ErrFriendRestricted: return e.Code == socialCodeRestricted || e.Code == socialCodeRestrictedPrivacy + case ErrBulkOperationLimit: + return e.Code == socialCodeBulkOperationLimit default: return false } diff --git a/social/error_test.go b/social/error_test.go index ee749e1b..7cf66edd 100644 --- a/social/error_test.go +++ b/social/error_test.go @@ -163,6 +163,7 @@ func TestResponseErrorMatchesCategories(t *testing.T) { {name: "rate limited", err: &ResponseError{StatusCode: http.StatusTooManyRequests}, target: ErrRateLimited, want: true}, {name: "retry after without rate limit", err: &ResponseError{StatusCode: http.StatusInternalServerError, RetryAfter: time.Second}, target: ErrRateLimited}, {name: "friend list full", err: &ResponseError{Code: 1028}, target: ErrFriendListFull, want: true}, + {name: "bulk operation limit", err: &ResponseError{Code: 1050}, target: ErrBulkOperationLimit, want: true}, {name: "restricted", err: &ResponseError{Code: 1011}, target: ErrFriendRestricted, want: true}, {name: "restricted alternate", err: &ResponseError{Code: 1049}, target: ErrFriendRestricted, want: true}, } @@ -175,6 +176,20 @@ func TestResponseErrorMatchesCategories(t *testing.T) { } } +func TestAddFriendsReturnsBulkOperationLimit(t *testing.T) { + client := New(&http.Client{Transport: roundTripFunc(func(req *http.Request) (*http.Response, error) { + return response(req, http.StatusBadRequest, `{"code":1050,"description":"too many users"}`), nil + })}, nil, xsts.UserInfo{}, nil) + + _, err := client.AddFriends(context.Background(), []string{"123", "456"}) + if err == nil { + t.Fatal("AddFriends returned nil error") + } + if !errors.Is(err, ErrBulkOperationLimit) { + t.Fatalf("errors.Is(ErrBulkOperationLimit) = false for %T: %v", err, err) + } +} + func TestResponseErrorPreservesMetadataWhenBodyReadFails(t *testing.T) { req, err := http.NewRequest(http.MethodGet, "https://peoplehub.xboxlive.com/users/me/people/social", nil) if err != nil {