@@ -44,6 +44,7 @@ function Send-SlackApi
4444 [ValidateNotNullOrEmpty ()]
4545 [hashtable ]$Body = @ { },
4646
47+ [Parameter ()]
4748 [ValidateNotNullOrEmpty ()]
4849 [ValidateScript ({
4950 if (-not $_ -and -not $Script :PSSlack.Token )
@@ -57,67 +58,115 @@ function Send-SlackApi
5758 })]
5859 [string ]$Token = $Script :PSSlack.Token ,
5960
61+ [Parameter ()]
6062 [string ]$Proxy = $Script :PSSlack.Proxy ,
6163
62- [switch ]$ForceVerbose = $Script :PSSlack.ForceVerbose
64+ [Parameter ()]
65+ [switch ]$ForceVerbose = $Script :PSSlack.ForceVerbose ,
66+
67+ # If specified, enables cursor-based pagination of results. See https://api.slack.com/docs/pagination
68+ # for the list of Slack REST API methods that support cursor-based pagination.
69+ [Parameter (ParameterSetName = " Pagination" )]
70+ [switch ]
71+ $EnablePagination ,
72+
73+ # Specifies the page size when using cursor-based pagination. Slack recommends a range of 100-200.
74+ # The default is 200. Note: Slack limits the max to 1000 on certain APIs. That limit may vary over
75+ # time and over different APIs.
76+ [Parameter (ParameterSetName = " Pagination" )]
77+ [ValidateRange (1 , 1000 )]
78+ [int ]
79+ $PageSize = 200 ,
80+
81+ # MaxNumberPages can be used to limit the number of pages returned from Slack. The default value is
82+ # 0 which represents no limit i.e. all results are returned.
83+ [Parameter (ParameterSetName = " Pagination" )]
84+ [ValidateRange (0 , [int ]::MaxValue)]
85+ [int ]
86+ $MaxNumberPages = 0
6387 )
88+
6489 $Params = @ {
6590 Uri = " https://slack.com/api/$Method "
6691 ErrorAction = ' Stop'
6792 }
68- if ($Proxy ) {
93+ if ($Proxy ) {
6994 $Params [' Proxy' ] = $Proxy
7095 }
71- if (-not $ForceVerbose ) {
72- $Params.Add (' Verbose' , $False )
96+ if (-not $ForceVerbose ) {
97+ $Params.Add (' Verbose' , $false )
7398 }
74- if ($ForceVerbose ) {
99+ if ($ForceVerbose ) {
75100 $Params.Add (' Verbose' , $true )
76101 }
77- $Body.token = $Token
78102
79- try {
80- $Response = $null
81- $Response = Invoke-RestMethod @Params - Body $Body
103+ if ($EnablePagination ) {
104+ $Params [' Uri' ] += " ?limit=$PageSize "
82105 }
83- catch {
84- # (HTTP 429 is "Too Many Requests")
85- if ($_.Exception.Response.StatusCode -eq 429 ) {
86-
87- # Get the time before we can try again.
88- if ( $_.Exception.Response.Headers -and $_.Exception.Response.Headers.Contains (' Retry-After' ) ) {
89- $RetryPeriod = $_.Exception.Response.Headers.GetValues (' Retry-After' )
90- if ($RetryPeriod -is [string []]) {
91- $RetryPeriod = [int ]$RetryPeriod [0 ]
106+
107+ $Body.token = $Token
108+ $pageCount = 0
109+ $hasMoreData = $true
110+ $paginationUriBase = $Params.Uri
111+
112+ do {
113+ try {
114+ $Response = $null
115+ $Response = Invoke-RestMethod @Params - Body $Body
116+ }
117+ catch {
118+ # (HTTP 429 is "Too Many Requests")
119+ if ($_.Exception.Response.StatusCode -eq 429 ) {
120+
121+ # Get the time before we can try again.
122+ if ($_.Exception.Response.Headers -and $_.Exception.Response.Headers.Contains (' Retry-After' ) ) {
123+ $RetryPeriod = $_.Exception.Response.Headers.GetValues (' Retry-After' )
124+ if ($RetryPeriod -is [string []]) {
125+ $RetryPeriod = [int ]$RetryPeriod [0 ]
126+ }
92127 }
128+ else {
129+ $RetryPeriod = 2
130+ }
131+
132+ Write-Verbose " Sleeping [$RetryPeriod ] seconds due to Slack 429 response"
133+ Start-Sleep - Seconds $RetryPeriod
134+ continue
135+ }
136+ elseif ($null -ne $_.ErrorDetails.Message ) {
137+ # Convert the error-message to an object. (Invoke-RestMethod will not return data by-default if a 4xx/5xx status code is generated.)
138+ $_.ErrorDetails.Message | ConvertFrom-Json | Parse- SlackError - Exception $_.Exception - ErrorAction Stop
93139 }
94140 else {
95- $RetryPeriod = 2
141+ Write-Error - Exception $_ .Exception - Message " Slack API call failed: $_ "
96142 }
97- Write-Verbose " Sleeping [$RetryPeriod ] seconds due to Slack 429 response"
98- Start-Sleep - Seconds $RetryPeriod
99- Send-SlackApi @PSBoundParameters
100-
101143 }
102- elseif ($_.ErrorDetails.Message -ne $null ) {
103- # Convert the error-message to an object. (Invoke-RestMethod will not return data by-default if a 4xx/5xx status code is generated.)
104- $_.ErrorDetails.Message | ConvertFrom-Json | Parse- SlackError - Exception $_.Exception - ErrorAction Stop
105144
145+ # Check to see if we have confirmation that our API call failed.
146+ # (Responses with exception-generating status codes are handled in the "catch" block above - this one is for errors that don't generate exceptions)
147+ if ($null -ne $Response -and $Response.ok -eq $false ) {
148+ $Response | Parse- SlackError
149+ break
150+ }
151+ elseif ($Response ) {
152+ Write-Output $Response
153+ if ($EnablePagination ) {
154+ $pageCount ++
155+
156+ $nextCursor = $Response.response_metadata.next_cursor
157+ if ($nextCursor ) {
158+ $encodedNextCursor = [System.Web.HttpUtility ]::UrlEncode($nextCursor )
159+ $Params [' Uri' ] = " ${paginationUriBase} &cursor=$encodedNextCursor "
160+ }
161+ else {
162+ $hasMoreData = $false
163+ }
164+ }
106165 }
107166 else {
108- Write-Error - Exception $_.Exception - Message " Slack API call failed: $_ "
167+ Write-Verbose " Something went wrong. `$ Response is `$ null"
168+ break
109169 }
110170 }
111-
112- # Check to see if we have confirmation that our API call failed.
113- # (Responses with exception-generating status codes are handled in the "catch" block above - this one is for errors that don't generate exceptions)
114- if ($Response -ne $null -and $Response.ok -eq $False ) {
115- $Response | Parse- SlackError
116- }
117- elseif ($Response ) {
118- Write-Output $Response
119- }
120- else {
121- Write-Verbose " Something went wrong. `$ Response is `$ null"
122- }
171+ while ($EnablePagination -and $hasMoreData -and ($MaxNumberPages -and ($pageCount -lt $MaxNumberPages )))
123172}
0 commit comments