Repository: mailgun/mailgun-go (go)

Issue:
mailgun.go looks have no Interface `UpdateDomainTracking`
mailgun.go looks have no Interface `UpdateDomainTracking` .
I'm trying to import/export mailgun settings to JSON, But I have no way to update `DomainTracking` settings to domain which I created.

Pull request description:
Support for updating domain tracking info
## [3.6.0-rc.1] - 2019-06-07
### Added
* Added UpdateClickTracking() to modify click tracking for a domain
* Added UpdateUnsubscribeTracking() to modify unsubscribe tracking for a domain
* Added UpdateOpenTracking() to modify open tracking for a domain

This fixes #192 


Patch:
diff --git a/CHANGELOG b/CHANGELOG
index 9c83c78..0991d35 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -4,6 +4,12 @@ All notable changes to this project will be documented in this file.
 The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
 and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
 
+## [3.6.0-rc.1] - 2019-06-07
+### Added
+* Added UpdateClickTracking() to modify click tracking for a domain
+* Added UpdateUnsubscribeTracking() to modify unsubscribe tracking for a domain
+* Added UpdateOpenTracking() to modify open tracking for a domain
+
 ## [3.5.0] - 2019-05-21
 ### Added
 * Added notice in README about go dep bug.
diff --git a/domains.go b/domains.go
index 4b04608..221c6ee 100644
--- a/domains.go
+++ b/domains.go
@@ -343,6 +343,41 @@ func (mg *MailgunImpl) GetDomainTracking(ctx context.Context, domain string) (Do
 	return resp.Tracking, err
 }
 
+func (mg *MailgunImpl) UpdateClickTracking(ctx context.Context, domain, active string) error {
+	r := newHTTPRequest(generatePublicApiUrl(mg, domainsEndpoint) + "/" + domain + "/tracking/click")
+	r.setClient(mg.Client())
+	r.setBasicAuth(basicAuthUser, mg.APIKey())
+
+	payload := newUrlEncodedPayload()
+	payload.addValue("active", active)
+	_, err := makePutRequest(ctx, r, payload)
+	return err
+}
+
+func (mg *MailgunImpl) UpdateUnsubscribeTracking(ctx context.Context, domain, active, htmlFooter, textFooter string) error {
+	r := newHTTPRequest(generatePublicApiUrl(mg, domainsEndpoint) + "/" + domain + "/tracking/unsubscribe")
+	r.setClient(mg.Client())
+	r.setBasicAuth(basicAuthUser, mg.APIKey())
+
+	payload := newUrlEncodedPayload()
+	payload.addValue("active", active)
+	payload.addValue("html_footer", htmlFooter)
+	payload.addValue("text_footer", textFooter)
+	_, err := makePutRequest(ctx, r, payload)
+	return err
+}
+
+func (mg *MailgunImpl) UpdateOpenTracking(ctx context.Context, domain, active string) error {
+	r := newHTTPRequest(generatePublicApiUrl(mg, domainsEndpoint) + "/" + domain + "/tracking/open")
+	r.setClient(mg.Client())
+	r.setBasicAuth(basicAuthUser, mg.APIKey())
+
+	payload := newUrlEncodedPayload()
+	payload.addValue("active", active)
+	_, err := makePutRequest(ctx, r, payload)
+	return err
+}
+
 func boolToString(b bool) string {
 	if b {
 		return "true"
diff --git a/mailgun.go b/mailgun.go
index 0349b3c..9b3a378 100644
--- a/mailgun.go
+++ b/mailgun.go
@@ -147,6 +147,9 @@ type Mailgun interface {
 	UpdateDomainConnection(ctx context.Context, domain string, dc DomainConnection) error
 	GetDomainConnection(ctx context.Context, domain string) (DomainConnection, error)
 	GetDomainTracking(ctx context.Context, domain string) (DomainTracking, error)
+	UpdateClickTracking(ctx context.Context, domain, active string) error
+	UpdateUnsubscribeTracking(ctx context.Context, domain, active, htmlFooter, textFooter string) error
+	UpdateOpenTracking(ctx context.Context, domain, active string) error
 
 	GetStoredMessage(ctx context.Context, url string) (StoredMessage, error)
 	GetStoredMessageRaw(ctx context.Context, id string) (StoredMessageRaw, error)
diff --git a/mock_domains.go b/mock_domains.go
index e50cc42..030c9ad 100644
--- a/mock_domains.go
+++ b/mock_domains.go
@@ -93,7 +93,9 @@ func (ms *MockServer) addDomainRoutes(r chi.Router) {
 	r.Get("/domains/{domain}/connection", ms.getConnection)
 	r.Put("/domains/{domain}/connection", ms.updateConnection)
 	r.Get("/domains/{domain}/tracking", ms.getTracking)
-	//r.Put("/domains/{domain}/tracking/{type}", ms.updateTracking)
+	r.Put("/domains/{domain}/tracking/click", ms.updateClickTracking)
+	r.Put("/domains/{domain}/tracking/open", ms.updateOpenTracking)
+	r.Put("/domains/{domain}/tracking/unsubscribe", ms.updateUnsubTracking)
 	r.Get("/domains/{domain}/limits/tag", ms.getTagLimits)
 }
 
@@ -222,6 +224,48 @@ func (ms *MockServer) getTracking(w http.ResponseWriter, r *http.Request) {
 	toJSON(w, okResp{Message: "domain not found"})
 }
 
+func (ms *MockServer) updateClickTracking(w http.ResponseWriter, r *http.Request) {
+	for i, d := range ms.domainList {
+		if d.Domain.Name == chi.URLParam(r, "domain") {
+			ms.domainList[i].Tracking.Click.Active = stringToBool(r.FormValue("active"))
+			toJSON(w, okResp{Message: "Domain tracking settings have been updated"})
+			return
+		}
+	}
+	w.WriteHeader(http.StatusNotFound)
+	toJSON(w, okResp{Message: "domain not found"})
+}
+
+func (ms *MockServer) updateOpenTracking(w http.ResponseWriter, r *http.Request) {
+	for i, d := range ms.domainList {
+		if d.Domain.Name == chi.URLParam(r, "domain") {
+			ms.domainList[i].Tracking.Open.Active = stringToBool(r.FormValue("active"))
+			toJSON(w, okResp{Message: "Domain tracking settings have been updated"})
+			return
+		}
+	}
+	w.WriteHeader(http.StatusNotFound)
+	toJSON(w, okResp{Message: "domain not found"})
+}
+
+func (ms *MockServer) updateUnsubTracking(w http.ResponseWriter, r *http.Request) {
+	for i, d := range ms.domainList {
+		if d.Domain.Name == chi.URLParam(r, "domain") {
+			ms.domainList[i].Tracking.Unsubscribe.Active = stringToBool(r.FormValue("active"))
+			if len(r.FormValue("html_footer")) != 0 {
+				ms.domainList[i].Tracking.Unsubscribe.HTMLFooter = r.FormValue("html_footer")
+			}
+			if len(r.FormValue("text_footer")) != 0 {
+				ms.domainList[i].Tracking.Unsubscribe.TextFooter = r.FormValue("text_footer")
+			}
+			toJSON(w, okResp{Message: "Domain tracking settings have been updated"})
+			return
+		}
+	}
+	w.WriteHeader(http.StatusNotFound)
+	toJSON(w, okResp{Message: "domain not found"})
+}
+
 func (ms *MockServer) getTagLimits(w http.ResponseWriter, r *http.Request) {
 	for _, d := range ms.domainList {
 		if d.Domain.Name == chi.URLParam(r, "domain") {


Test patch:
diff --git a/domains_test.go b/domains_test.go
index 729e7be..f6e2885 100644
--- a/domains_test.go
+++ b/domains_test.go
@@ -117,6 +117,32 @@ func TestDomainTracking(t *testing.T) {
 	ensure.DeepEqual(t, len(info.Unsubscribe.TextFooter) != 0, true)
 	ensure.DeepEqual(t, info.Click.Active, true)
 	ensure.DeepEqual(t, info.Open.Active, true)
+
+	// Click Tracking
+	err = mg.UpdateClickTracking(ctx, testDomain, "no")
+	ensure.Nil(t, err)
+
+	info, err = mg.GetDomainTracking(ctx, testDomain)
+	ensure.Nil(t, err)
+	ensure.DeepEqual(t, info.Click.Active, false)
+
+	// Open Tracking
+	err = mg.UpdateOpenTracking(ctx, testDomain, "no")
+	ensure.Nil(t, err)
+
+	info, err = mg.GetDomainTracking(ctx, testDomain)
+	ensure.Nil(t, err)
+	ensure.DeepEqual(t, info.Open.Active, false)
+
+	// Unsubscribe
+	err = mg.UpdateUnsubscribeTracking(ctx, testDomain, "yes", "<h2>Hi</h2>", "Hi")
+	ensure.Nil(t, err)
+
+	info, err = mg.GetDomainTracking(ctx, testDomain)
+	ensure.Nil(t, err)
+	ensure.DeepEqual(t, info.Unsubscribe.Active, true)
+	ensure.DeepEqual(t, info.Unsubscribe.HTMLFooter, "<h2>Hi</h2>")
+	ensure.DeepEqual(t, info.Unsubscribe.TextFooter, "Hi")
 }
 
 func TestDomainVerify(t *testing.T) {