273 lines
		
	
	
		
			7.9 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			273 lines
		
	
	
		
			7.9 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| package mailgun
 | |
| 
 | |
| import (
 | |
| 	"context"
 | |
| 	"strconv"
 | |
| )
 | |
| 
 | |
| // A Route structure contains information on a configured or to-be-configured route.
 | |
| // When creating a new route, the SDK only uses a subset of the fields of this structure.
 | |
| // In particular, CreatedAt and ID are meaningless in this context, and will be ignored.
 | |
| // Only Priority, Description, Expression, and Actions need be provided.
 | |
| type Route struct {
 | |
| 	// The Priority field indicates how soon the route works relative to other configured routes.
 | |
| 	// Routes of equal priority are consulted in chronological order.
 | |
| 	Priority int `json:"priority,omitempty"`
 | |
| 	// The Description field provides a human-readable description for the route.
 | |
| 	// Mailgun ignores this field except to provide the description when viewing the Mailgun web control panel.
 | |
| 	Description string `json:"description,omitempty"`
 | |
| 	// The Expression field lets you specify a pattern to match incoming messages against.
 | |
| 	Expression string `json:"expression,omitempty"`
 | |
| 	// The Actions field contains strings specifying what to do
 | |
| 	// with any message which matches the provided expression.
 | |
| 	Actions []string `json:"actions,omitempty"`
 | |
| 
 | |
| 	// The CreatedAt field provides a time-stamp for when the route came into existence.
 | |
| 	CreatedAt RFC2822Time `json:"created_at,omitempty"`
 | |
| 	// ID field provides a unique identifier for this route.
 | |
| 	Id string `json:"id,omitempty"`
 | |
| }
 | |
| 
 | |
| type routesListResponse struct {
 | |
| 	// is -1 if Next() or First() have not been called
 | |
| 	TotalCount int     `json:"total_count"`
 | |
| 	Items      []Route `json:"items"`
 | |
| }
 | |
| 
 | |
| type createRouteResp struct {
 | |
| 	Message string `json:"message"`
 | |
| 	Route   `json:"route"`
 | |
| }
 | |
| 
 | |
| // ListRoutes allows you to iterate through a list of routes returned by the API
 | |
| func (mg *MailgunImpl) ListRoutes(opts *ListOptions) *RoutesIterator {
 | |
| 	var limit int
 | |
| 	if opts != nil {
 | |
| 		limit = opts.Limit
 | |
| 	}
 | |
| 
 | |
| 	if limit == 0 {
 | |
| 		limit = 100
 | |
| 	}
 | |
| 
 | |
| 	return &RoutesIterator{
 | |
| 		mg:                 mg,
 | |
| 		url:                generatePublicApiUrl(mg, routesEndpoint),
 | |
| 		routesListResponse: routesListResponse{TotalCount: -1},
 | |
| 		limit:              limit,
 | |
| 	}
 | |
| }
 | |
| 
 | |
| type RoutesIterator struct {
 | |
| 	routesListResponse
 | |
| 
 | |
| 	limit  int
 | |
| 	mg     Mailgun
 | |
| 	offset int
 | |
| 	url    string
 | |
| 	err    error
 | |
| }
 | |
| 
 | |
| // If an error occurred during iteration `Err()` will return non nil
 | |
| func (ri *RoutesIterator) Err() error {
 | |
| 	return ri.err
 | |
| }
 | |
| 
 | |
| // Offset returns the current offset of the iterator
 | |
| func (ri *RoutesIterator) Offset() int {
 | |
| 	return ri.offset
 | |
| }
 | |
| 
 | |
| // Next retrieves the next page of items from the api. Returns false when there
 | |
| // no more pages to retrieve or if there was an error. Use `.Err()` to retrieve
 | |
| // the error
 | |
| func (ri *RoutesIterator) Next(ctx context.Context, items *[]Route) bool {
 | |
| 	if ri.err != nil {
 | |
| 		return false
 | |
| 	}
 | |
| 
 | |
| 	ri.err = ri.fetch(ctx, ri.offset, ri.limit)
 | |
| 	if ri.err != nil {
 | |
| 		return false
 | |
| 	}
 | |
| 
 | |
| 	cpy := make([]Route, len(ri.Items))
 | |
| 	copy(cpy, ri.Items)
 | |
| 	*items = cpy
 | |
| 	if len(ri.Items) == 0 {
 | |
| 		return false
 | |
| 	}
 | |
| 	ri.offset = ri.offset + len(ri.Items)
 | |
| 	return true
 | |
| }
 | |
| 
 | |
| // First retrieves the first page of items from the api. Returns false if there
 | |
| // was an error. It also sets the iterator object to the first page.
 | |
| // Use `.Err()` to retrieve the error.
 | |
| func (ri *RoutesIterator) First(ctx context.Context, items *[]Route) bool {
 | |
| 	if ri.err != nil {
 | |
| 		return false
 | |
| 	}
 | |
| 	ri.err = ri.fetch(ctx, 0, ri.limit)
 | |
| 	if ri.err != nil {
 | |
| 		return false
 | |
| 	}
 | |
| 	cpy := make([]Route, len(ri.Items))
 | |
| 	copy(cpy, ri.Items)
 | |
| 	*items = cpy
 | |
| 	ri.offset = len(ri.Items)
 | |
| 	return true
 | |
| }
 | |
| 
 | |
| // Last retrieves the last page of items from the api.
 | |
| // Calling Last() is invalid unless you first call First() or Next()
 | |
| // Returns false if there was an error. It also sets the iterator object
 | |
| // to the last page. Use `.Err()` to retrieve the error.
 | |
| func (ri *RoutesIterator) Last(ctx context.Context, items *[]Route) bool {
 | |
| 	if ri.err != nil {
 | |
| 		return false
 | |
| 	}
 | |
| 
 | |
| 	if ri.TotalCount == -1 {
 | |
| 		return false
 | |
| 	}
 | |
| 
 | |
| 	ri.offset = ri.TotalCount - ri.limit
 | |
| 	if ri.offset < 0 {
 | |
| 		ri.offset = 0
 | |
| 	}
 | |
| 
 | |
| 	ri.err = ri.fetch(ctx, ri.offset, ri.limit)
 | |
| 	if ri.err != nil {
 | |
| 		return false
 | |
| 	}
 | |
| 	cpy := make([]Route, len(ri.Items))
 | |
| 	copy(cpy, ri.Items)
 | |
| 	*items = cpy
 | |
| 	return true
 | |
| }
 | |
| 
 | |
| // Previous retrieves the previous page of items from the api. Returns false when there
 | |
| // no more pages to retrieve or if there was an error. Use `.Err()` to retrieve
 | |
| // the error if any
 | |
| func (ri *RoutesIterator) Previous(ctx context.Context, items *[]Route) bool {
 | |
| 	if ri.err != nil {
 | |
| 		return false
 | |
| 	}
 | |
| 
 | |
| 	if ri.TotalCount == -1 {
 | |
| 		return false
 | |
| 	}
 | |
| 
 | |
| 	ri.offset = ri.offset - (ri.limit * 2)
 | |
| 	if ri.offset < 0 {
 | |
| 		ri.offset = 0
 | |
| 	}
 | |
| 
 | |
| 	ri.err = ri.fetch(ctx, ri.offset, ri.limit)
 | |
| 	if ri.err != nil {
 | |
| 		return false
 | |
| 	}
 | |
| 	cpy := make([]Route, len(ri.Items))
 | |
| 	copy(cpy, ri.Items)
 | |
| 	*items = cpy
 | |
| 	if len(ri.Items) == 0 {
 | |
| 		return false
 | |
| 	}
 | |
| 	return true
 | |
| }
 | |
| 
 | |
| func (ri *RoutesIterator) fetch(ctx context.Context, skip, limit int) error {
 | |
| 	r := newHTTPRequest(ri.url)
 | |
| 	r.setBasicAuth(basicAuthUser, ri.mg.APIKey())
 | |
| 	r.setClient(ri.mg.Client())
 | |
| 
 | |
| 	if skip != 0 {
 | |
| 		r.addParameter("skip", strconv.Itoa(skip))
 | |
| 	}
 | |
| 	if limit != 0 {
 | |
| 		r.addParameter("limit", strconv.Itoa(limit))
 | |
| 	}
 | |
| 
 | |
| 	return getResponseFromJSON(ctx, r, &ri.routesListResponse)
 | |
| }
 | |
| 
 | |
| // CreateRoute installs a new route for your domain.
 | |
| // The route structure you provide serves as a template, and
 | |
| // only a subset of the fields influence the operation.
 | |
| // See the Route structure definition for more details.
 | |
| func (mg *MailgunImpl) CreateRoute(ctx context.Context, prototype Route) (_ignored Route, err error) {
 | |
| 	r := newHTTPRequest(generatePublicApiUrl(mg, routesEndpoint))
 | |
| 	r.setClient(mg.Client())
 | |
| 	r.setBasicAuth(basicAuthUser, mg.APIKey())
 | |
| 	p := newUrlEncodedPayload()
 | |
| 	p.addValue("priority", strconv.Itoa(prototype.Priority))
 | |
| 	p.addValue("description", prototype.Description)
 | |
| 	p.addValue("expression", prototype.Expression)
 | |
| 	for _, action := range prototype.Actions {
 | |
| 		p.addValue("action", action)
 | |
| 	}
 | |
| 	var resp createRouteResp
 | |
| 	if err = postResponseFromJSON(ctx, r, p, &resp); err != nil {
 | |
| 		return _ignored, err
 | |
| 	}
 | |
| 	return resp.Route, err
 | |
| }
 | |
| 
 | |
| // DeleteRoute removes the specified route from your domain's configuration.
 | |
| // To avoid ambiguity, Mailgun identifies the route by unique ID.
 | |
| // See the Route structure definition and the Mailgun API documentation for more details.
 | |
| func (mg *MailgunImpl) DeleteRoute(ctx context.Context, id string) error {
 | |
| 	r := newHTTPRequest(generatePublicApiUrl(mg, routesEndpoint) + "/" + id)
 | |
| 	r.setClient(mg.Client())
 | |
| 	r.setBasicAuth(basicAuthUser, mg.APIKey())
 | |
| 	_, err := makeDeleteRequest(ctx, r)
 | |
| 	return err
 | |
| }
 | |
| 
 | |
| // GetRoute retrieves the complete route definition associated with the unique route ID.
 | |
| func (mg *MailgunImpl) GetRoute(ctx context.Context, id string) (Route, error) {
 | |
| 	r := newHTTPRequest(generatePublicApiUrl(mg, routesEndpoint) + "/" + id)
 | |
| 	r.setClient(mg.Client())
 | |
| 	r.setBasicAuth(basicAuthUser, mg.APIKey())
 | |
| 	var envelope struct {
 | |
| 		Message string `json:"message"`
 | |
| 		*Route  `json:"route"`
 | |
| 	}
 | |
| 	err := getResponseFromJSON(ctx, r, &envelope)
 | |
| 	if err != nil {
 | |
| 		return Route{}, err
 | |
| 	}
 | |
| 	return *envelope.Route, err
 | |
| 
 | |
| }
 | |
| 
 | |
| // UpdateRoute provides an "in-place" update of the specified route.
 | |
| // Only those route fields which are non-zero or non-empty are updated.
 | |
| // All other fields remain as-is.
 | |
| func (mg *MailgunImpl) UpdateRoute(ctx context.Context, id string, route Route) (Route, error) {
 | |
| 	r := newHTTPRequest(generatePublicApiUrl(mg, routesEndpoint) + "/" + id)
 | |
| 	r.setClient(mg.Client())
 | |
| 	r.setBasicAuth(basicAuthUser, mg.APIKey())
 | |
| 	p := newUrlEncodedPayload()
 | |
| 	if route.Priority != 0 {
 | |
| 		p.addValue("priority", strconv.Itoa(route.Priority))
 | |
| 	}
 | |
| 	if route.Description != "" {
 | |
| 		p.addValue("description", route.Description)
 | |
| 	}
 | |
| 	if route.Expression != "" {
 | |
| 		p.addValue("expression", route.Expression)
 | |
| 	}
 | |
| 	if route.Actions != nil {
 | |
| 		for _, action := range route.Actions {
 | |
| 			p.addValue("action", action)
 | |
| 		}
 | |
| 	}
 | |
| 	// For some reason, this API function just returns a bare Route on success.
 | |
| 	// Unsure why this is the case; it seems like it ought to be a bug.
 | |
| 	var envelope Route
 | |
| 	err := putResponseFromJSON(ctx, r, p, &envelope)
 | |
| 	return envelope, err
 | |
| }
 |