github.com/mailgun/mailgun-go/v3@v3.6.4/routes.go (about)

     1  package mailgun
     2  
     3  import (
     4  	"context"
     5  	"strconv"
     6  )
     7  
     8  // A Route structure contains information on a configured or to-be-configured route.
     9  // When creating a new route, the SDK only uses a subset of the fields of this structure.
    10  // In particular, CreatedAt and ID are meaningless in this context, and will be ignored.
    11  // Only Priority, Description, Expression, and Actions need be provided.
    12  type Route struct {
    13  	// The Priority field indicates how soon the route works relative to other configured routes.
    14  	// Routes of equal priority are consulted in chronological order.
    15  	Priority int `json:"priority,omitempty"`
    16  	// The Description field provides a human-readable description for the route.
    17  	// Mailgun ignores this field except to provide the description when viewing the Mailgun web control panel.
    18  	Description string `json:"description,omitempty"`
    19  	// The Expression field lets you specify a pattern to match incoming messages against.
    20  	Expression string `json:"expression,omitempty"`
    21  	// The Actions field contains strings specifying what to do
    22  	// with any message which matches the provided expression.
    23  	Actions []string `json:"actions,omitempty"`
    24  
    25  	// The CreatedAt field provides a time-stamp for when the route came into existence.
    26  	CreatedAt RFC2822Time `json:"created_at,omitempty"`
    27  	// ID field provides a unique identifier for this route.
    28  	Id string `json:"id,omitempty"`
    29  }
    30  
    31  type routesListResponse struct {
    32  	// is -1 if Next() or First() have not been called
    33  	TotalCount int     `json:"total_count"`
    34  	Items      []Route `json:"items"`
    35  }
    36  
    37  type createRouteResp struct {
    38  	Message string `json:"message"`
    39  	Route   `json:"route"`
    40  }
    41  
    42  // ListRoutes allows you to iterate through a list of routes returned by the API
    43  func (mg *MailgunImpl) ListRoutes(opts *ListOptions) *RoutesIterator {
    44  	var limit int
    45  	if opts != nil {
    46  		limit = opts.Limit
    47  	}
    48  
    49  	if limit == 0 {
    50  		limit = 100
    51  	}
    52  
    53  	return &RoutesIterator{
    54  		mg:                 mg,
    55  		url:                generatePublicApiUrl(mg, routesEndpoint),
    56  		routesListResponse: routesListResponse{TotalCount: -1},
    57  		limit:              limit,
    58  	}
    59  }
    60  
    61  type RoutesIterator struct {
    62  	routesListResponse
    63  
    64  	limit  int
    65  	mg     Mailgun
    66  	offset int
    67  	url    string
    68  	err    error
    69  }
    70  
    71  // If an error occurred during iteration `Err()` will return non nil
    72  func (ri *RoutesIterator) Err() error {
    73  	return ri.err
    74  }
    75  
    76  // Offset returns the current offset of the iterator
    77  func (ri *RoutesIterator) Offset() int {
    78  	return ri.offset
    79  }
    80  
    81  // Next retrieves the next page of items from the api. Returns false when there
    82  // no more pages to retrieve or if there was an error. Use `.Err()` to retrieve
    83  // the error
    84  func (ri *RoutesIterator) Next(ctx context.Context, items *[]Route) bool {
    85  	if ri.err != nil {
    86  		return false
    87  	}
    88  
    89  	ri.err = ri.fetch(ctx, ri.offset, ri.limit)
    90  	if ri.err != nil {
    91  		return false
    92  	}
    93  
    94  	cpy := make([]Route, len(ri.Items))
    95  	copy(cpy, ri.Items)
    96  	*items = cpy
    97  	if len(ri.Items) == 0 {
    98  		return false
    99  	}
   100  	ri.offset = ri.offset + len(ri.Items)
   101  	return true
   102  }
   103  
   104  // First retrieves the first page of items from the api. Returns false if there
   105  // was an error. It also sets the iterator object to the first page.
   106  // Use `.Err()` to retrieve the error.
   107  func (ri *RoutesIterator) First(ctx context.Context, items *[]Route) bool {
   108  	if ri.err != nil {
   109  		return false
   110  	}
   111  	ri.err = ri.fetch(ctx, 0, ri.limit)
   112  	if ri.err != nil {
   113  		return false
   114  	}
   115  	cpy := make([]Route, len(ri.Items))
   116  	copy(cpy, ri.Items)
   117  	*items = cpy
   118  	ri.offset = len(ri.Items)
   119  	return true
   120  }
   121  
   122  // Last retrieves the last page of items from the api.
   123  // Calling Last() is invalid unless you first call First() or Next()
   124  // Returns false if there was an error. It also sets the iterator object
   125  // to the last page. Use `.Err()` to retrieve the error.
   126  func (ri *RoutesIterator) Last(ctx context.Context, items *[]Route) bool {
   127  	if ri.err != nil {
   128  		return false
   129  	}
   130  
   131  	if ri.TotalCount == -1 {
   132  		return false
   133  	}
   134  
   135  	ri.offset = ri.TotalCount - ri.limit
   136  	if ri.offset < 0 {
   137  		ri.offset = 0
   138  	}
   139  
   140  	ri.err = ri.fetch(ctx, ri.offset, ri.limit)
   141  	if ri.err != nil {
   142  		return false
   143  	}
   144  	cpy := make([]Route, len(ri.Items))
   145  	copy(cpy, ri.Items)
   146  	*items = cpy
   147  	return true
   148  }
   149  
   150  // Previous retrieves the previous page of items from the api. Returns false when there
   151  // no more pages to retrieve or if there was an error. Use `.Err()` to retrieve
   152  // the error if any
   153  func (ri *RoutesIterator) Previous(ctx context.Context, items *[]Route) bool {
   154  	if ri.err != nil {
   155  		return false
   156  	}
   157  
   158  	if ri.TotalCount == -1 {
   159  		return false
   160  	}
   161  
   162  	ri.offset = ri.offset - (ri.limit * 2)
   163  	if ri.offset < 0 {
   164  		ri.offset = 0
   165  	}
   166  
   167  	ri.err = ri.fetch(ctx, ri.offset, ri.limit)
   168  	if ri.err != nil {
   169  		return false
   170  	}
   171  	cpy := make([]Route, len(ri.Items))
   172  	copy(cpy, ri.Items)
   173  	*items = cpy
   174  	if len(ri.Items) == 0 {
   175  		return false
   176  	}
   177  	return true
   178  }
   179  
   180  func (ri *RoutesIterator) fetch(ctx context.Context, skip, limit int) error {
   181  	r := newHTTPRequest(ri.url)
   182  	r.setBasicAuth(basicAuthUser, ri.mg.APIKey())
   183  	r.setClient(ri.mg.Client())
   184  
   185  	if skip != 0 {
   186  		r.addParameter("skip", strconv.Itoa(skip))
   187  	}
   188  	if limit != 0 {
   189  		r.addParameter("limit", strconv.Itoa(limit))
   190  	}
   191  
   192  	return getResponseFromJSON(ctx, r, &ri.routesListResponse)
   193  }
   194  
   195  // CreateRoute installs a new route for your domain.
   196  // The route structure you provide serves as a template, and
   197  // only a subset of the fields influence the operation.
   198  // See the Route structure definition for more details.
   199  func (mg *MailgunImpl) CreateRoute(ctx context.Context, prototype Route) (_ignored Route, err error) {
   200  	r := newHTTPRequest(generatePublicApiUrl(mg, routesEndpoint))
   201  	r.setClient(mg.Client())
   202  	r.setBasicAuth(basicAuthUser, mg.APIKey())
   203  	p := newUrlEncodedPayload()
   204  	p.addValue("priority", strconv.Itoa(prototype.Priority))
   205  	p.addValue("description", prototype.Description)
   206  	p.addValue("expression", prototype.Expression)
   207  	for _, action := range prototype.Actions {
   208  		p.addValue("action", action)
   209  	}
   210  	var resp createRouteResp
   211  	if err = postResponseFromJSON(ctx, r, p, &resp); err != nil {
   212  		return _ignored, err
   213  	}
   214  	return resp.Route, err
   215  }
   216  
   217  // DeleteRoute removes the specified route from your domain's configuration.
   218  // To avoid ambiguity, Mailgun identifies the route by unique ID.
   219  // See the Route structure definition and the Mailgun API documentation for more details.
   220  func (mg *MailgunImpl) DeleteRoute(ctx context.Context, id string) error {
   221  	r := newHTTPRequest(generatePublicApiUrl(mg, routesEndpoint) + "/" + id)
   222  	r.setClient(mg.Client())
   223  	r.setBasicAuth(basicAuthUser, mg.APIKey())
   224  	_, err := makeDeleteRequest(ctx, r)
   225  	return err
   226  }
   227  
   228  // GetRoute retrieves the complete route definition associated with the unique route ID.
   229  func (mg *MailgunImpl) GetRoute(ctx context.Context, id string) (Route, error) {
   230  	r := newHTTPRequest(generatePublicApiUrl(mg, routesEndpoint) + "/" + id)
   231  	r.setClient(mg.Client())
   232  	r.setBasicAuth(basicAuthUser, mg.APIKey())
   233  	var envelope struct {
   234  		Message string `json:"message"`
   235  		*Route  `json:"route"`
   236  	}
   237  	err := getResponseFromJSON(ctx, r, &envelope)
   238  	if err != nil {
   239  		return Route{}, err
   240  	}
   241  	return *envelope.Route, err
   242  
   243  }
   244  
   245  // UpdateRoute provides an "in-place" update of the specified route.
   246  // Only those route fields which are non-zero or non-empty are updated.
   247  // All other fields remain as-is.
   248  func (mg *MailgunImpl) UpdateRoute(ctx context.Context, id string, route Route) (Route, error) {
   249  	r := newHTTPRequest(generatePublicApiUrl(mg, routesEndpoint) + "/" + id)
   250  	r.setClient(mg.Client())
   251  	r.setBasicAuth(basicAuthUser, mg.APIKey())
   252  	p := newUrlEncodedPayload()
   253  	if route.Priority != 0 {
   254  		p.addValue("priority", strconv.Itoa(route.Priority))
   255  	}
   256  	if route.Description != "" {
   257  		p.addValue("description", route.Description)
   258  	}
   259  	if route.Expression != "" {
   260  		p.addValue("expression", route.Expression)
   261  	}
   262  	if route.Actions != nil {
   263  		for _, action := range route.Actions {
   264  			p.addValue("action", action)
   265  		}
   266  	}
   267  	// For some reason, this API function just returns a bare Route on success.
   268  	// Unsure why this is the case; it seems like it ought to be a bug.
   269  	var envelope Route
   270  	err := putResponseFromJSON(ctx, r, p, &envelope)
   271  	return envelope, err
   272  }