From cbe9190ea4870c80ce400a36c520413b792fcae3 Mon Sep 17 00:00:00 2001 From: Parth Sharma <86726240+parth-deepsource@users.noreply.github.com> Date: Fri, 27 Oct 2023 17:41:55 +0530 Subject: [PATCH] fix: paginate slack channel list (#71) * fix: paginate slack channel list * chore: fix DeepSource issues --- provider/slack/client.go | 59 ++++++++++++++++++++++++++++++++++------ provider/slack/slack.go | 10 +------ 2 files changed, 51 insertions(+), 18 deletions(-) diff --git a/provider/slack/client.go b/provider/slack/client.go index 60ebba7..8fb7c99 100644 --- a/provider/slack/client.go +++ b/provider/slack/client.go @@ -6,6 +6,7 @@ import ( "fmt" "io" "net/http" + "net/url" "github.com/deepsourcelabs/hermes/domain" "github.com/deepsourcelabs/hermes/provider" @@ -92,16 +93,28 @@ type Channel struct { Name string `json:"name"` } +type ResponseMetadata struct { + NextCursor string `json:"next_cursor"` +} + type GetChannelsResponse struct { - Ok bool `json:"ok"` - Channels []Channel `json:"channels"` + Ok bool `json:"ok"` + Channels []Channel `json:"channels"` + ResponseMetadata ResponseMetadata `json:"response_metadata"` } -func (c *Client) GetChannels(request *GetChannelsRequest) (*GetChannelsResponse, domain.IError) { - req, err := http.NewRequest("GET", getChannelsURL, http.NoBody) +func (c *Client) getChannelsPage(request *GetChannelsRequest, cursor string) (*GetChannelsResponse, domain.IError) { + var response = new(GetChannelsResponse) + + requestUrl := getChannelsURL + if cursor != "" { + requestUrl += "&cursor=" + url.QueryEscape(cursor) + } + + req, err := http.NewRequest("GET", requestUrl, http.NoBody) if err != nil { log.Errorf("slack: failed creating request for options: %v", err) - return nil, errFailedOptsFetch(err.Error()) + return response, errFailedOptsFetch(err.Error()) } req.Header.Add("Authorization", fmt.Sprintf("Bearer %s", request.BearerToken)) @@ -110,18 +123,46 @@ func (c *Client) GetChannels(request *GetChannelsRequest) (*GetChannelsResponse, resp, err := c.HTTPClient.Do(req) if err != nil { log.Errorf("slack: failed sending request for options: %v", err) - return nil, errFailedOptsFetch(err.Error()) + return response, errFailedOptsFetch(err.Error()) } + defer resp.Body.Close() + if resp.StatusCode < 200 || resp.StatusCode > 399 { log.Errorf("slack: Non 2xx response while fetching options: %v", err) - return nil, handleHTTPFailure(resp) + return response, handleHTTPFailure(resp) } - var response = new(GetChannelsResponse) if err := json.NewDecoder(resp.Body).Decode(response); err != nil { log.Errorf("slack: Non 2xx response while fetching options: %v", err) - return nil, errFailedOptsFetch(err.Error()) + return response, errFailedOptsFetch(err.Error()) } return response, nil } + +func (c *Client) GetChannels(request *GetChannelsRequest) ([]map[string]string, domain.IError) { + var channels []map[string]string + cursor := "" + + for { + response, err := c.getChannelsPage(request, cursor) + if err != nil { + log.Errorf("slack: Error fetching page %v: %v", cursor, err) + return channels, err + } + + for _, v := range response.Channels { + channels = append(channels, map[string]string{ + "id": v.ID, + "name": v.Name, + }) + } + + cursor = response.ResponseMetadata.NextCursor + if cursor == "" { + break + } + } + + return channels, nil +} diff --git a/provider/slack/slack.go b/provider/slack/slack.go index 1698fb7..bd11086 100644 --- a/provider/slack/slack.go +++ b/provider/slack/slack.go @@ -123,19 +123,11 @@ func (p *defaultSlack) GetOptValues(_ context.Context, secret *domain.NotifierSe request := &GetChannelsRequest{ BearerToken: secret.Token, } - response, err := p.Client.GetChannels(request) + channels, err := p.Client.GetChannels(request) if err != nil { log.Errorf("slack: failed to get channels : %v", err) return nil, err } - channels := []map[string]string{} - - for _, v := range response.Channels { - channels = append(channels, map[string]string{ - "id": v.ID, - "name": v.Name, - }) - } return map[string]interface{}{"channel": channels}, nil }