diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d4d57f3..508c378 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -16,7 +16,7 @@ jobs: strategy: max-parallel: 1 matrix: - goVer: ['1.17', '1.18'] + goVer: ['1.17', '1.18', '1.19', '1.20', '1.21', '1.22'] steps: - uses: actions/checkout@v3 diff --git a/unread_counts.go b/unread_counts.go new file mode 100644 index 0000000..1035f2c --- /dev/null +++ b/unread_counts.go @@ -0,0 +1,53 @@ +package stream_chat + +import ( + "context" + "net/http" + "net/url" + "time" +) + +type UnreadCountsChannel struct { + ChannelID string `json:"channel_id"` + UnreadCount int `json:"unread_count"` + LastRead time.Time `json:"last_read"` +} + +type UnreadCountsChannelType struct { + ChannelType string `json:"channel_type"` + ChannelCount int `json:"channel_count"` + UnreadCount int `json:"unread_count"` +} + +type UnreadCountsThread struct { + UnreadCount int `json:"unread_count"` + LastRead time.Time `json:"last_read"` + LastReadMessageID string `json:"last_read_message_id"` + ParentMessageID string `json:"parent_message_id"` +} + +type UnreadCountsResponse struct { + TotalUnreadCount int `json:"total_unread_count"` + TotalUnreadThreadsCount int `json:"total_unread_threads_count"` + Channels []UnreadCountsChannel `json:"channels"` + ChannelType []UnreadCountsChannelType `json:"channel_type"` + Threads []UnreadCountsThread `json:"threads"` + Response +} + +func (c *Client) UnreadCounts(ctx context.Context, userID string) (*UnreadCountsResponse, error) { + var resp UnreadCountsResponse + err := c.makeRequest(ctx, http.MethodGet, "unread", url.Values{"user_id": []string{userID}}, nil, &resp) + return &resp, err +} + +type UnreadCountsBatchResponse struct { + CountsByUser map[string]*UnreadCountsResponse `json:"counts_by_user"` + Response +} + +func (c *Client) UnreadCountsBatch(ctx context.Context, userIDs []string) (*UnreadCountsBatchResponse, error) { + var resp UnreadCountsBatchResponse + err := c.makeRequest(ctx, http.MethodPost, "unread_batch", nil, map[string][]string{"user_ids": userIDs}, &resp) + return &resp, err +} diff --git a/unread_counts_test.go b/unread_counts_test.go new file mode 100644 index 0000000..9c83cdb --- /dev/null +++ b/unread_counts_test.go @@ -0,0 +1,113 @@ +package stream_chat + +import ( + "context" + "strings" + "testing" + + "github.com/stretchr/testify/require" +) + +func TestUnreadCounts(t *testing.T) { + c := initClient(t) + user := randomUser(t, c) + ch := initChannel(t, c, user.ID) + + ctx := context.Background() + msg := &Message{Text: "test message"} + randSender := randomString(5) + var messageID string + for i := 0; i < 5; i++ { + resp, err := ch.SendMessage(ctx, msg, randSender) + require.NoError(t, err) + messageID = resp.Message.ID + } + + resp, err := c.UnreadCounts(ctx, user.ID) + require.NoError(t, err) + require.Equal(t, 5, resp.TotalUnreadCount) + require.Equal(t, 1, len(resp.Channels)) + require.Equal(t, ch.CID, resp.Channels[0].ChannelID) + require.Equal(t, 5, resp.Channels[0].UnreadCount) + require.Equal(t, 1, len(resp.ChannelType)) + require.Equal(t, strings.Split(ch.CID, ":")[0], resp.ChannelType[0].ChannelType) + require.Equal(t, 5, resp.ChannelType[0].UnreadCount) + + // test unread threads + threadMsg := &Message{Text: "test thread", ParentID: messageID} + _, err = ch.SendMessage(ctx, threadMsg, user.ID) + require.NoError(t, err) + _, err = ch.SendMessage(ctx, threadMsg, randSender) + require.NoError(t, err) + + resp, err = c.UnreadCounts(ctx, user.ID) + require.NoError(t, err) + require.Equal(t, 1, resp.TotalUnreadThreadsCount) + require.Equal(t, 1, len(resp.Threads)) + require.Equal(t, messageID, resp.Threads[0].ParentMessageID) +} + +func TestUnreadCountsBatch(t *testing.T) { + c := initClient(t) + user1 := randomUser(t, c) + user2 := randomUser(t, c) + ch := initChannel(t, c, user1.ID, user2.ID) + + ctx := context.Background() + msg := &Message{Text: "test message"} + randSender := randomString(5) + var messageID string + for i := 0; i < 5; i++ { + resp, err := ch.SendMessage(ctx, msg, randSender) + require.NoError(t, err) + messageID = resp.Message.ID + } + + nonexistant := randomString(5) + resp, err := c.UnreadCountsBatch(ctx, []string{user1.ID, user2.ID, nonexistant}) + require.NoError(t, err) + require.Equal(t, 2, len(resp.CountsByUser)) + require.Contains(t, resp.CountsByUser, user1.ID) + require.Contains(t, resp.CountsByUser, user2.ID) + require.NotContains(t, resp.CountsByUser, nonexistant) + + // user 1 counts + require.Equal(t, 5, resp.CountsByUser[user1.ID].TotalUnreadCount) + require.Equal(t, 1, len(resp.CountsByUser[user1.ID].Channels)) + require.Equal(t, ch.CID, resp.CountsByUser[user1.ID].Channels[0].ChannelID) + require.Equal(t, 5, resp.CountsByUser[user1.ID].Channels[0].UnreadCount) + require.Equal(t, 1, len(resp.CountsByUser[user1.ID].ChannelType)) + require.Equal(t, strings.Split(ch.CID, ":")[0], resp.CountsByUser[user1.ID].ChannelType[0].ChannelType) + require.Equal(t, 5, resp.CountsByUser[user1.ID].ChannelType[0].UnreadCount) + + // user 2 counts + require.Equal(t, 5, resp.CountsByUser[user2.ID].TotalUnreadCount) + require.Equal(t, 1, len(resp.CountsByUser[user2.ID].Channels)) + require.Equal(t, ch.CID, resp.CountsByUser[user2.ID].Channels[0].ChannelID) + require.Equal(t, 5, resp.CountsByUser[user2.ID].Channels[0].UnreadCount) + require.Equal(t, 1, len(resp.CountsByUser[user2.ID].ChannelType)) + require.Equal(t, strings.Split(ch.CID, ":")[0], resp.CountsByUser[user2.ID].ChannelType[0].ChannelType) + require.Equal(t, 5, resp.CountsByUser[user2.ID].ChannelType[0].UnreadCount) + + // test unread threads + threadMsg := &Message{Text: "test thread", ParentID: messageID} + _, err = ch.SendMessage(ctx, threadMsg, user1.ID) + require.NoError(t, err) + _, err = ch.SendMessage(ctx, threadMsg, user2.ID) + require.NoError(t, err) + _, err = ch.SendMessage(ctx, threadMsg, randSender) + require.NoError(t, err) + + resp, err = c.UnreadCountsBatch(ctx, []string{user1.ID, user2.ID, nonexistant}) + require.NoError(t, err) + + // user 1 thread counts + require.Equal(t, 1, resp.CountsByUser[user1.ID].TotalUnreadThreadsCount) + require.Equal(t, 1, len(resp.CountsByUser[user1.ID].Threads)) + require.Equal(t, messageID, resp.CountsByUser[user1.ID].Threads[0].ParentMessageID) + + // user 2 thread counts + require.Equal(t, 1, resp.CountsByUser[user2.ID].TotalUnreadThreadsCount) + require.Equal(t, 1, len(resp.CountsByUser[user2.ID].Threads)) + require.Equal(t, messageID, resp.CountsByUser[user2.ID].Threads[0].ParentMessageID) +}