Skip to content

Commit

Permalink
Merge pull request #1 from gordcurrie/gc/contactChanges
Browse files Browse the repository at this point in the history
Added contact functionality
  • Loading branch information
markstgodard authored Jan 8, 2018
2 parents 2add90d + 237ee4b commit 40f4f30
Show file tree
Hide file tree
Showing 3 changed files with 282 additions and 0 deletions.
76 changes: 76 additions & 0 deletions hubspot/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,82 @@ func (c *Client) SingleEmail(emailId int, emailTo string) error {
return err
}

// Hubspot Create or update a contact
// example https://api.hubapi.com/contacts/v1/contact/createOrUpdate/email/testingapis@hubspot.com/?hapikey=demo
func (c *Client) CreateOrUpdateContact(emailAddress string, properties []Property) (response, error) {
req := ContactBody{
Properties: properties,
}

body, err := json.Marshal(req)
if err != nil {
return response{}, fmt.Errorf("invalid request:", err)
}

response, err := c.doRequest(request{
URL: fmt.Sprintf("%s/contacts/v1/contact/createOrUpdate/email/%s/?hapikey=%s", c.baseUrl, emailAddress, c.apiKey),
Method: http.MethodPost,
Body: body,
OkStatusCode: http.StatusOK,
})

return response, err
}

// Hubspot add contact to list
// example https://api.hubapi.com/contacts/v1/lists/226468/add?hapikey=demo
func (c *Client) AddContactsToList(emails []string, listId int) (response, error) {
return c.updateListWithContacts(listId, emails, "add")
}

func (c *Client) RemoveContactsFromList(emails []string, listId int) (response, error) {
return c.updateListWithContacts(listId, emails, "remove")
}

// Hubspot remove contact to list
// example https://api.hubapi.com/contacts/v1/lists/226468/remove?hapikey=demo
func (c *Client) updateListWithContacts(listId int, emails []string, method string) (response, error) {
req := ListBody{
Emails: emails,
}

body, err := json.Marshal(req)
if err != nil {
return response{}, fmt.Errorf("invalid request:", err)
}

response, err := c.doRequest(request{
URL: fmt.Sprintf("%s/contacts/v1/lists/%d/%s?hapikey=%s", c.baseUrl, listId, method, c.apiKey),
Method: http.MethodPost,
Body: body,
OkStatusCode: http.StatusOK,
})

return response, err
}

// Hubspot add contact to workflow
// example https://api.hubapi.com/automation/v2/workflows/10900/enrollments/contacts/testingapis@hubspot.com?hapikey=demo
func (c *Client) AddContactToWorkFlow(email string, workflowId int) error {
return c.updateWorkflowForClient(email, workflowId, http.MethodPost)
}

// Hubspot remove contact from workflow
// example https://api.hubapi.com/automation/v2/workflows/10900/enrollments/contacts/testingapis@hubspot.com?hapikey=demo
func (c *Client) RemoveContactFromWorkFlow(email string, workflowId int) error {
return c.updateWorkflowForClient(email, workflowId, http.MethodDelete)
}

func (c *Client) updateWorkflowForClient(email string, workflowId int, method string) error {
_, err := c.doRequest(request{
URL: fmt.Sprintf("%s/automation/v2/workflows/%d/enrollments/contacts/%s?hapikey=%s", c.baseUrl, workflowId, email, c.apiKey),
Method: method,
OkStatusCode: http.StatusNoContent,
})

return err
}

type request struct {
URL string
Method string
Expand Down
192 changes: 192 additions & 0 deletions hubspot/client_test.go
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
package hubspot_test

import (
"encoding/json"
"net/http"
"net/http/httptest"
"regexp"
"strings"

"github.com/bold-commerce/go-hubspot/hubspot"
Expand Down Expand Up @@ -51,6 +53,196 @@ var _ = Describe("Client", func() {
})

})

Describe("CreateOrUpdateContact", func() {
var (
server *httptest.Server
)

BeforeEach(func() {
response, _ := json.Marshal(map[string]interface{}{"vid": 751, "isNew": true})

server = httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if strings.Contains(r.RequestURI, "/contacts/v1/contact/createOrUpdate/email/") {
w.WriteHeader(http.StatusOK)
w.Write([]byte(response))
} else {
w.WriteHeader(http.StatusInternalServerError)
}
}))

client = hubspot.NewClient(server.URL, "my-api-key")
Expect(client).ToNot(BeNil())
})

AfterEach(func() {
server.Close()
})

It("creates an email an returns response from api", func() {
properties := []hubspot.Property{hubspot.Property{}}
response, err := client.CreateOrUpdateContact("gord.currie@boldcommerce.com", properties)
Expect(err).NotTo(HaveOccurred())
Expect(string(response.Body)).To(Equal(`{"isNew":true,"vid":751}`))
Expect(response.StatusCode).To(Equal(http.StatusOK))
})
})

Describe("AddContactsToList", func() {
var (
server *httptest.Server
)

BeforeEach(func() {
response, _ := json.Marshal(map[string]interface{}{"updated": []int{751}, "discarded": []int{}, "invalidVids": []int{}, "invalidEmails": []string{}})

server = httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
match, _ := regexp.MatchString(".*contacts/v1/lists/\\d*/add\\?hapikey=.*", r.RequestURI)
if match {
w.WriteHeader(http.StatusOK)
w.Write([]byte(response))
} else {
w.WriteHeader(http.StatusInternalServerError)
}
}))

client = hubspot.NewClient(server.URL, "my-api-key")
Expect(client).ToNot(BeNil())
})

AfterEach(func() {
server.Close()
})

It("removes emails from list and returns response from api", func() {
emails := []string{"gord.currie@boldcommerce.com"}
response, err := client.AddContactsToList(emails, 5)
Expect(err).NotTo(HaveOccurred())
Expect(response.StatusCode).To(Equal(http.StatusOK))
})
})

Describe("RemoveContactsFromList", func() {
var (
server *httptest.Server
)

BeforeEach(func() {
response, _ := json.Marshal(map[string]interface{}{"updated": []int{751}, "discarded": []int{}, "invalidVids": []int{}, "invalidEmails": []string{}})

server = httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
match, _ := regexp.MatchString(".*contacts/v1/lists/\\d*/remove\\?hapikey=.*", r.RequestURI)
if match {
w.WriteHeader(http.StatusOK)
w.Write([]byte(response))
} else {
w.WriteHeader(http.StatusInternalServerError)
}
}))

client = hubspot.NewClient(server.URL, "my-api-key")
Expect(client).ToNot(BeNil())
})

AfterEach(func() {
server.Close()
})

It("removes emails from list and returns response from api", func() {
emails := []string{"gord.currie@boldcommerce.com"}
response, err := client.RemoveContactsFromList(emails, 5)
Expect(err).NotTo(HaveOccurred())
Expect(response.StatusCode).To(Equal(http.StatusOK))
})
})

Describe("AddContactToWorkFlow", func() {
var (
server *httptest.Server
)

AfterEach(func() {
server.Close()
})

It("removes email from workflow", func() {
server = httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
match, _ := regexp.MatchString(".*automation/v2/workflows/\\d*/enrollments/contacts/.*", r.RequestURI)
if match {
w.WriteHeader(http.StatusNoContent)
} else {
w.WriteHeader(http.StatusInternalServerError)
}
}))

client = hubspot.NewClient(server.URL, "my-api-key")
Expect(client).ToNot(BeNil())

err := client.AddContactToWorkFlow("gord.currie@boldcommerce.com", 2494115)
Expect(err).NotTo(HaveOccurred())
})

It("returns an error if the contact email is not found", func() {
server = httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
match, _ := regexp.MatchString(".*automation/v2/workflows/\\d*/enrollments/contacts/.*", r.RequestURI)
if match {
w.WriteHeader(http.StatusNotFound)
} else {
w.WriteHeader(http.StatusInternalServerError)
}
}))

client = hubspot.NewClient(server.URL, "my-api-key")
Expect(client).ToNot(BeNil())

err := client.AddContactToWorkFlow("gord.currie@boldcommerce.com", 2494115)
Expect(err).To(MatchError(ContainSubstring("Error: 404 Not Found")))
})
})

Describe("RemoveContactFromWorkFlow", func() {
var (
server *httptest.Server
)

AfterEach(func() {
server.Close()
})

It("removes email from workflow", func() {
server = httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
match, _ := regexp.MatchString(".*automation/v2/workflows/\\d*/enrollments/contacts/.*", r.RequestURI)
if match {
w.WriteHeader(http.StatusNoContent)
} else {
w.WriteHeader(http.StatusInternalServerError)
}
}))

client = hubspot.NewClient(server.URL, "my-api-key")
Expect(client).ToNot(BeNil())

err := client.RemoveContactFromWorkFlow("gord.currie@boldcommerce.com", 2494115)
Expect(err).NotTo(HaveOccurred())
})

It("returns an error if the contact email is not found", func() {
server = httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
match, _ := regexp.MatchString(".*automation/v2/workflows/\\d*/enrollments/contacts/.*", r.RequestURI)
if match {
w.WriteHeader(http.StatusNotFound)
} else {
w.WriteHeader(http.StatusInternalServerError)
}
}))

client = hubspot.NewClient(server.URL, "my-api-key")
Expect(client).ToNot(BeNil())

err := client.RemoveContactFromWorkFlow("gord.currie@boldcommerce.com", 2494115)
Expect(err).To(MatchError(ContainSubstring("Error: 404 Not Found")))
})
})
})

const singleEmailResp = `{
Expand Down
14 changes: 14 additions & 0 deletions hubspot/contact.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package hubspot

type ContactBody struct {
Properties []Property `json:"properties"`
}

type Property struct {
Property string `json:"property"`
Value interface{} `json:"value"`
}

type ListBody struct {
Emails []string `json:"emails"`
}

0 comments on commit 40f4f30

Please sign in to comment.