From 3692d126440e61e4511b3b3fc7d8d39173dd749a Mon Sep 17 00:00:00 2001 From: Lennart Kuijs Date: Wed, 4 Dec 2024 15:17:14 +0100 Subject: [PATCH] feat: added support for MemberPartialUpdate --- channel.go | 60 ++++++++++++++++++++++++++++++++++++++++++++----- channel_test.go | 35 +++++++++++++++++++++++++++++ 2 files changed, 89 insertions(+), 6 deletions(-) diff --git a/channel.go b/channel.go index 740654a..c55eb42 100644 --- a/channel.go +++ b/channel.go @@ -23,17 +23,48 @@ type ChannelMember struct { User *User `json:"user,omitempty"` IsModerator bool `json:"is_moderator,omitempty"` - Invited bool `json:"invited,omitempty"` - InviteAcceptedAt *time.Time `json:"invite_accepted_at,omitempty"` - InviteRejectedAt *time.Time `json:"invite_rejected_at,omitempty"` - Role string `json:"role,omitempty"` - ArchivedAt *time.Time `json:"archived_at,omitempty"` - PinnedAt *time.Time `json:"pinned_at,omitempty"` + Invited bool `json:"invited,omitempty"` + InviteAcceptedAt *time.Time `json:"invite_accepted_at,omitempty"` + InviteRejectedAt *time.Time `json:"invite_rejected_at,omitempty"` + Status string `json:"status,omitempty"` + Role string `json:"role,omitempty"` + ChannelRole string `json:"channel_role"` + Banned bool `json:"banned"` + BanExpires *time.Time `json:"ban_expires,omitempty"` + ShadowBanned bool `json:"shadow_banned"` + ArchivedAt *time.Time `json:"archived_at,omitempty"` + PinnedAt *time.Time `json:"pinned_at,omitempty"` + NotificationsMuted bool `json:"notifications_muted"` + + ExtraData map[string]interface{} `json:"-"` CreatedAt time.Time `json:"created_at,omitempty"` UpdatedAt time.Time `json:"updated_at,omitempty"` } +type channelMemberForJSON ChannelMember + +// UnmarshalJSON implements json.Unmarshaler. +func (m *ChannelMember) UnmarshalJSON(data []byte) error { + var m2 channelMemberForJSON + if err := json.Unmarshal(data, &m2); err != nil { + return err + } + *m = ChannelMember(m2) + + if err := json.Unmarshal(data, &m.ExtraData); err != nil { + return err + } + + removeFromMap(m.ExtraData, *m) + return nil +} + +// MarshalJSON implements json.Marshaler. +func (m ChannelMember) MarshalJSON() ([]byte, error) { + return addToMapAndMarshal(m.ExtraData, channelMemberForJSON(m)) +} + type Channel struct { ID string `json:"id"` Type string `json:"type"` @@ -863,6 +894,7 @@ type ChannelMemberResponse struct { Response } +// Pin pins the channel for the user. func (ch *Channel) Pin(ctx context.Context, userID string) (*ChannelMemberResponse, error) { if userID == "" { return nil, errors.New("user ID must be not empty") @@ -881,6 +913,7 @@ func (ch *Channel) Pin(ctx context.Context, userID string) (*ChannelMemberRespon return resp, err } +// Unpin unpins the channel for the user. func (ch *Channel) Unpin(ctx context.Context, userID string) (*ChannelMemberResponse, error) { if userID == "" { return nil, errors.New("user ID must be not empty") @@ -899,6 +932,7 @@ func (ch *Channel) Unpin(ctx context.Context, userID string) (*ChannelMemberResp return resp, err } +// Archive archives the channel for the user. func (ch *Channel) Archive(ctx context.Context, userID string) (*ChannelMemberResponse, error) { if userID == "" { return nil, errors.New("user ID must be not empty") @@ -917,6 +951,7 @@ func (ch *Channel) Archive(ctx context.Context, userID string) (*ChannelMemberRe return resp, err } +// Unarchive unarchives the channel for the user. func (ch *Channel) Unarchive(ctx context.Context, userID string) (*ChannelMemberResponse, error) { if userID == "" { return nil, errors.New("user ID must be not empty") @@ -934,3 +969,16 @@ func (ch *Channel) Unarchive(ctx context.Context, userID string) (*ChannelMember err := ch.client.makeRequest(ctx, http.MethodPatch, p, nil, data, resp) return resp, err } + +// PartialUpdateMember set and unset specific fields when it is necessary to retain additional custom data fields on the object. AKA a patch style update. +func (ch *Channel) PartialUpdateMember(ctx context.Context, userID string, update PartialUpdate) (*ChannelMemberResponse, error) { + if userID == "" { + return nil, errors.New("user ID must be not empty") + } + + p := path.Join("channels", url.PathEscape(ch.Type), url.PathEscape(ch.ID), "member", url.PathEscape(userID)) + + resp := &ChannelMemberResponse{} + err := ch.client.makeRequest(ctx, http.MethodPatch, p, nil, update, resp) + return resp, err +} diff --git a/channel_test.go b/channel_test.go index 32b7a56..0495517 100644 --- a/channel_test.go +++ b/channel_test.go @@ -493,6 +493,41 @@ func TestChannel_PartialUpdate(t *testing.T) { require.Nil(t, ch.ExtraData["age"]) } +func TestChannel_MemberPartialUpdate(t *testing.T) { + c := initClient(t) + users := randomUsers(t, c, 5) + ctx := context.Background() + + members := make([]string, 0, len(users)) + for i := range users { + members = append(members, users[i].ID) + } + + req := &ChannelRequest{Members: members} + resp, err := c.CreateChannel(ctx, "team", randomString(12), randomUser(t, c).ID, req) + require.NoError(t, err) + + ch := resp.Channel + member, err := ch.PartialUpdateMember(ctx, members[0], PartialUpdate{ + Set: map[string]interface{}{ + "color": "red", + }, + Unset: []string{"age"}, + }) + require.NoError(t, err) + require.Equal(t, "red", member.ChannelMember.ExtraData["color"]) + + member, err = ch.PartialUpdateMember(ctx, members[0], PartialUpdate{ + Set: map[string]interface{}{ + "age": "18", + }, + Unset: []string{"color"}, + }) + require.NoError(t, err) + require.Equal(t, "18", member.ChannelMember.ExtraData["age"]) + require.Nil(t, member.ChannelMember.ExtraData["color"]) +} + func TestChannel_SendFile(t *testing.T) { c := initClient(t) ch := initChannel(t, c)