@@ -20,7 +20,9 @@ import (
2020 "errors"
2121 "fmt"
2222 "net/http"
23+ "net/url"
2324 "strings"
25+ "time"
2426
2527 "github.com/orijtech/otils"
2628)
@@ -98,7 +100,7 @@ type Phone struct {
98100
99101type CurrencyCode string
100102
101- type DeliveryResponse struct {
103+ type Delivery struct {
102104 ID string `json:"delivery_id"`
103105 Fee float32 `json:"fee"`
104106 QuoteID string `json:"quote_id"`
@@ -196,7 +198,7 @@ func (e *Endpoint) Validate() error {
196198 return nil
197199}
198200
199- func (c * Client ) RequestDelivery (req * DeliveryRequest ) (* DeliveryResponse , error ) {
201+ func (c * Client ) RequestDelivery (req * DeliveryRequest ) (* Delivery , error ) {
200202 if err := req .Validate (); err != nil {
201203 return nil , err
202204 }
@@ -215,7 +217,7 @@ func (c *Client) RequestDelivery(req *DeliveryRequest) (*DeliveryResponse, error
215217 if err != nil {
216218 return nil , err
217219 }
218- dRes := new (DeliveryResponse )
220+ dRes := new (Delivery )
219221 if err := json .Unmarshal (blob , dRes ); err != nil {
220222 return nil , err
221223 }
@@ -240,3 +242,149 @@ func (c *Client) CancelDelivery(deliveryID string) error {
240242 _ , _ , err = c .doHTTPReq (httpReq )
241243 return err
242244}
245+
246+ type DeliveryListRequest struct {
247+ Status Status `json:"status,omitempty"`
248+ LimitPerPage int64 `json:"limit"`
249+ MaxPageNumber int64 `json:"max_page,omitempty"`
250+ StartOffset int64 `json:"offset"`
251+
252+ ThrottleDurationMs int64 `json:"throttle_duration_ms"`
253+ }
254+
255+ type DeliveryThread struct {
256+ Pages chan * DeliveryPage `json:"-"`
257+ Cancel func ()
258+ }
259+
260+ type DeliveryPage struct {
261+ Err error `json:"error"`
262+ PageNumber int64 `json:"page_number,omitempty"`
263+ Deliveries []* Delivery `json:"deliveries,omitempty"`
264+ }
265+
266+ type recvDelivery struct {
267+ Count int64 `json:"count"`
268+ NextPageQuery string `json:"next_page"`
269+ PreviousPageQuery string `json:"previous_page"`
270+ Deliveries []* Delivery `json:"deliveries"`
271+ }
272+
273+ type deliveryPager struct {
274+ Offset int64 `json:"offset"`
275+ Limit int64 `json:"limit"`
276+ Status Status `json:"status"`
277+ }
278+
279+ const (
280+ NoThrottle = - 1
281+
282+ defaultThrottleDurationMs = 150 * time .Millisecond
283+ )
284+
285+ // ListDeliveries requires authorization with OAuth2.0 with
286+ // the delivery scope set.
287+ func (c * Client ) ListDeliveries (dReq * DeliveryListRequest ) (* DeliveryThread , error ) {
288+ if dReq == nil {
289+ dReq = & DeliveryListRequest {Status : StatusReceiptReady }
290+ }
291+
292+ baseURL := c .legacyV1BaseURL ()
293+ fullURL := fmt .Sprintf ("%s/deliveries" , baseURL )
294+ qv , err := otils .ToURLValues (& deliveryPager {
295+ Limit : dReq .LimitPerPage ,
296+ Status : dReq .Status ,
297+ Offset : dReq .StartOffset ,
298+ })
299+ if err != nil {
300+ return nil , err
301+ }
302+
303+ if len (qv ) > 0 {
304+ fullURL = fmt .Sprintf ("%s/deliveries?%s" , baseURL , qv .Encode ())
305+ }
306+
307+ parsedURL , err := url .Parse (fullURL )
308+ if err != nil {
309+ return nil , err
310+ }
311+ parsedBaseURL , err := url .Parse (baseURL )
312+ if err != nil {
313+ return nil , err
314+ }
315+
316+ var errsList []string
317+ if want , got := parsedBaseURL .Scheme , parsedURL .Scheme ; got != want {
318+ errsList = append (errsList , fmt .Sprintf ("gotScheme=%q wantBaseScheme=%q" , got , want ))
319+ }
320+ if want , got := parsedBaseURL .Host , parsedURL .Host ; got != want {
321+ errsList = append (errsList , fmt .Sprintf ("gotHost=%q wantBaseHost=%q" , got , want ))
322+ }
323+ if len (errsList ) > 0 {
324+ return nil , errors .New (strings .Join (errsList , "\n " ))
325+ }
326+
327+ maxPage := dReq .MaxPageNumber
328+ pageExceeded := func (pageNumber int64 ) bool {
329+ return maxPage > 0 && pageNumber >= maxPage
330+ }
331+
332+ fullDeliveriesBaseURL := fmt .Sprintf ("%s/deliveries" , baseURL )
333+ resChan := make (chan * DeliveryPage )
334+ cancelChan , cancelFn := makeCancelParadigm ()
335+
336+ go func () {
337+ defer close (resChan )
338+
339+ pageNumber := int64 (0 )
340+ throttleDurationMs := defaultThrottleDurationMs
341+ if dReq .ThrottleDurationMs == NoThrottle {
342+ throttleDurationMs = 0
343+ } else {
344+ throttleDurationMs = time .Duration (dReq .ThrottleDurationMs ) * time .Millisecond
345+ }
346+
347+ for {
348+ page := & DeliveryPage {PageNumber : pageNumber }
349+
350+ req , err := http .NewRequest ("GET" , fullURL , nil )
351+ if err != nil {
352+ page .Err = err
353+ resChan <- page
354+ return
355+ }
356+
357+ slurp , _ , err := c .doReq (req )
358+ if err != nil {
359+ page .Err = err
360+ resChan <- page
361+ return
362+ }
363+
364+ recv := new (recvDelivery )
365+ if err := json .Unmarshal (slurp , recv ); err != nil {
366+ page .Err = err
367+ resChan <- page
368+ return
369+ }
370+
371+ page .Deliveries = recv .Deliveries
372+ resChan <- page
373+ pageNumber += 1
374+ pageToken := recv .NextPageQuery
375+ if pageExceeded (pageNumber ) || pageToken == "" || len (recv .Deliveries ) == 0 {
376+ return
377+ }
378+
379+ fullURL = fmt .Sprintf ("%s?%s" , fullDeliveriesBaseURL , pageToken )
380+
381+ select {
382+ case <- cancelChan :
383+ return
384+ case <- time .After (throttleDurationMs ):
385+ }
386+ }
387+ }()
388+
389+ return & DeliveryThread {Cancel : cancelFn , Pages : resChan }, nil
390+ }
0 commit comments