aboutsummaryrefslogtreecommitdiffstats
path: root/ship.go
diff options
context:
space:
mode:
Diffstat (limited to 'ship.go')
-rw-r--r--ship.go84
1 files changed, 62 insertions, 22 deletions
diff --git a/ship.go b/ship.go
index b5aa822..d76661a 100644
--- a/ship.go
+++ b/ship.go
@@ -3,10 +3,14 @@ package lulu
import (
"encoding/json"
"fmt"
+ email "net/mail"
+ "regexp"
)
//go:generate go run github.com/yawnak/string-enumer -t ShippingLevel -t Title --text -o ./ship_gen.go .
+var phoneExpr = regexp.MustCompile(`^\+?[\d\s\-.\/()]{8,20}$`)
+
// ShippingLevel is the quality/speed with which a package is shipped.
type ShippingLevel string
@@ -28,32 +32,32 @@ type ShippingAddress struct {
IsBusiness bool // Only relevant for US addresses. Some US carriers don't deliver to business-addresses on Saturday.
Name string // Full name of the person, including first and last name.
Title Title
- Organization string // Name of an organization. Required if no person name is given.
- Email string // Shipping carriers require an email address for notifications or handling delivery issues. If no email is given, the default email in the user profile will be used.
- Phone string // Shipping carriers require a phone number for handling delivery issues. If no phone number is given, the default in the API user profile will be used.
- TaxId string // The recipient’s tax identification number. Required for shipping addresses to Brazil, Chile, and Mexico.
+ Organization string // Name of an organization. Required if no person name is given.
+ Email *email.Address // Shipping carriers require an email address for notifications or handling delivery issues. If no email is given, the default email in the user profile will be used.
+ Phone PhoneNumber // Shipping carriers require a phone number for handling delivery issues. If no phone number is given, the default in the API user profile will be used.
+ TaxId string // The recipient’s tax identification number. Required for shipping addresses to Brazil, Chile, and Mexico.
}
// They use "country" in some places, "country_code" in others, etc.
// This is the union of all of them.
type shippingAddress struct {
- Country string `json:"country"`
- CountryCode string `json:"country_code"`
- State string `json:"state"`
- StateCode string `json:"state_code"`
- City string `json:"city"`
- Street1 string `json:"street1"`
- Street2 string `json:"street2"`
- PostCode string `json:"postcode"`
- IsBusiness bool `json:"is_business"`
- Name string `json:"name"`
- FirstName string `json:"first_name"`
- LastName string `json:"last_name"`
- Title Title `json:"title"`
- Organization string `json:"organization"`
- Email string `json:"email"`
- Phone string `json:"phone_number"`
- TaxId string `json:"recipient_tax_id"`
+ Country string `json:"country"`
+ CountryCode string `json:"country_code"`
+ State string `json:"state"`
+ StateCode string `json:"state_code"`
+ City string `json:"city"`
+ Street1 string `json:"street1"`
+ Street2 string `json:"street2"`
+ PostCode string `json:"postcode"`
+ IsBusiness bool `json:"is_business"`
+ Name string `json:"name"`
+ FirstName string `json:"first_name"`
+ LastName string `json:"last_name"`
+ Title Title `json:"title"`
+ Organization string `json:"organization"`
+ Email string `json:"email"`
+ Phone PhoneNumber `json:"phone_number"`
+ TaxId string `json:"recipient_tax_id"`
}
func (a *ShippingAddress) UnmarshalJSON(data []byte) error {
@@ -98,7 +102,15 @@ func (a *ShippingAddress) UnmarshalJSON(data []byte) error {
a.Title = alias.Title
a.Organization = alias.Organization
- a.Email = alias.Email
+
+ if alias.Email != "" {
+ addr, err := email.ParseAddress(alias.Email)
+ if err != nil {
+ return err
+ }
+ a.Email = addr
+ }
+
a.Phone = alias.Phone
a.TaxId = alias.TaxId
@@ -123,3 +135,31 @@ const (
Ms Title = "MS"
Dr Title = "DR"
)
+
+type PhoneNumber string
+
+func ParsePhoneNumber(s string) (PhoneNumber, error) {
+ if phoneExpr.MatchString(s) {
+ return PhoneNumber(s), nil
+ }
+ return "", fmt.Errorf("malformed phone number %q; must fit pattern `%s`", s, phoneExpr.String())
+}
+
+// MustParsePhoneNumber is like ParsePhoneNumber but panics if the phone
+// number cannot be parsed.
+func MustParsePhoneNumber(s string) PhoneNumber {
+ n, err := ParsePhoneNumber(s)
+ if err != nil {
+ panic(fmt.Sprintf("lulu: ParsePhoneNumber(%q): %v", s, err))
+ }
+ return n
+}
+
+func (n *PhoneNumber) UnmarshalText(text []byte) error {
+ pn, err := ParsePhoneNumber(string(text))
+ if err != nil {
+ return err
+ }
+ *n = pn
+ return nil
+}