Mailchimp report plugin
This commit is contained in:
234
plugins/mailchimp/chimp_api.go
Normal file
234
plugins/mailchimp/chimp_api.go
Normal file
@@ -0,0 +1,234 @@
|
||||
package mailchimp
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"regexp"
|
||||
"sync"
|
||||
)
|
||||
|
||||
const (
|
||||
reports_endpoint string = "/3.0/reports"
|
||||
reports_endpoint_campaign string = "/3.0/reports/%s"
|
||||
)
|
||||
|
||||
var mailchimp_datacenter = regexp.MustCompile("[a-z]+[0-9]+$")
|
||||
|
||||
type ChimpAPI struct {
|
||||
Transport http.RoundTripper
|
||||
Debug bool
|
||||
|
||||
sync.Mutex
|
||||
|
||||
url *url.URL
|
||||
}
|
||||
|
||||
type ReportsParams struct {
|
||||
Count string
|
||||
Offset string
|
||||
SinceSendTime string
|
||||
BeforeSendTime string
|
||||
}
|
||||
|
||||
func (p *ReportsParams) String() string {
|
||||
v := url.Values{}
|
||||
if p.Count != "" {
|
||||
v.Set("count", p.Count)
|
||||
}
|
||||
if p.Offset != "" {
|
||||
v.Set("offset", p.Offset)
|
||||
}
|
||||
if p.BeforeSendTime != "" {
|
||||
v.Set("before_send_time", p.BeforeSendTime)
|
||||
}
|
||||
if p.SinceSendTime != "" {
|
||||
v.Set("since_send_time", p.SinceSendTime)
|
||||
}
|
||||
return v.Encode()
|
||||
}
|
||||
|
||||
func NewChimpAPI(apiKey string) *ChimpAPI {
|
||||
u := &url.URL{}
|
||||
u.Scheme = "https"
|
||||
u.Host = fmt.Sprintf("%s.api.mailchimp.com", mailchimp_datacenter.FindString(apiKey))
|
||||
u.User = url.UserPassword("", apiKey)
|
||||
return &ChimpAPI{url: u}
|
||||
}
|
||||
|
||||
type APIError struct {
|
||||
Status int `json:"status"`
|
||||
Type string `json:"type"`
|
||||
Title string `json:"title"`
|
||||
Detail string `json:"detail"`
|
||||
Instance string `json:"instance"`
|
||||
}
|
||||
|
||||
func (e APIError) Error() string {
|
||||
return fmt.Sprintf("ERROR %v: %v. See %v", e.Status, e.Title, e.Type)
|
||||
}
|
||||
|
||||
func chimpErrorCheck(body []byte) error {
|
||||
var e APIError
|
||||
json.Unmarshal(body, &e)
|
||||
if e.Title != "" || e.Status != 0 {
|
||||
return e
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (a *ChimpAPI) GetReports(params ReportsParams) (ReportsResponse, error) {
|
||||
a.Lock()
|
||||
defer a.Unlock()
|
||||
a.url.Path = reports_endpoint
|
||||
|
||||
var response ReportsResponse
|
||||
rawjson, err := runChimp(a, params)
|
||||
if err != nil {
|
||||
return response, err
|
||||
}
|
||||
|
||||
err = json.Unmarshal(rawjson, &response)
|
||||
if err != nil {
|
||||
return response, err
|
||||
}
|
||||
|
||||
return response, nil
|
||||
}
|
||||
|
||||
func (a *ChimpAPI) GetReport(campaignID string) (Report, error) {
|
||||
a.Lock()
|
||||
defer a.Unlock()
|
||||
a.url.Path = fmt.Sprintf(reports_endpoint_campaign, campaignID)
|
||||
|
||||
var response Report
|
||||
rawjson, err := runChimp(a, ReportsParams{})
|
||||
if err != nil {
|
||||
return response, err
|
||||
}
|
||||
|
||||
err = json.Unmarshal(rawjson, &response)
|
||||
if err != nil {
|
||||
return response, err
|
||||
}
|
||||
|
||||
return response, nil
|
||||
}
|
||||
|
||||
func runChimp(api *ChimpAPI, params ReportsParams) ([]byte, error) {
|
||||
client := &http.Client{Transport: api.Transport}
|
||||
|
||||
var b bytes.Buffer
|
||||
req, err := http.NewRequest("GET", api.url.String(), &b)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
req.URL.RawQuery = params.String()
|
||||
req.Header.Set("User-Agent", "Telegraf-MailChimp-Plugin")
|
||||
if api.Debug {
|
||||
log.Printf("Request URL: %s", req.URL.String())
|
||||
}
|
||||
|
||||
resp, err := client.Do(req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
body, err := ioutil.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if api.Debug {
|
||||
log.Printf("Response Body:%s", string(body))
|
||||
}
|
||||
|
||||
if err = chimpErrorCheck(body); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return body, nil
|
||||
}
|
||||
|
||||
type ReportsResponse struct {
|
||||
Reports []Report `json:"reports"`
|
||||
TotalItems int `json:"total_items"`
|
||||
}
|
||||
|
||||
type Report struct {
|
||||
ID string `json:"id"`
|
||||
CampaignTitle string `json:"campaign_title"`
|
||||
Type string `json:"type"`
|
||||
EmailsSent int `json:"emails_sent"`
|
||||
AbuseReports int `json:"abuse_reports"`
|
||||
Unsubscribed int `json:"unsubscribed"`
|
||||
SendTime string `json:"send_time"`
|
||||
|
||||
TimeSeries []TimeSerie
|
||||
Bounces Bounces `json:"bounces"`
|
||||
Forwards Forwards `json:"forwards"`
|
||||
Opens Opens `json:"opens"`
|
||||
Clicks Clicks `json:"clicks"`
|
||||
FacebookLikes FacebookLikes `json:"facebook_likes"`
|
||||
IndustryStats IndustryStats `json:"industry_stats"`
|
||||
ListStats ListStats `json:"list_stats"`
|
||||
}
|
||||
|
||||
type Bounces struct {
|
||||
HardBounces int `json:"hard_bounces"`
|
||||
SoftBounces int `json:"soft_bounces"`
|
||||
SyntaxErrors int `json:"syntax_errors"`
|
||||
}
|
||||
|
||||
type Forwards struct {
|
||||
ForwardsCount int `json:"forwards_count"`
|
||||
ForwardsOpens int `json:"forwards_opens"`
|
||||
}
|
||||
|
||||
type Opens struct {
|
||||
OpensTotal int `json:"opens_total"`
|
||||
UniqueOpens int `json:"unique_opens"`
|
||||
OpenRate float64 `json:"open_rate"`
|
||||
LastOpen string `json:"last_open"`
|
||||
}
|
||||
|
||||
type Clicks struct {
|
||||
ClicksTotal int `json:"clicks_total"`
|
||||
UniqueClicks int `json:"unique_clicks"`
|
||||
UniqueSubscriberClicks int `json:"unique_subscriber_clicks"`
|
||||
ClickRate float64 `json:"click_rate"`
|
||||
LastClick string `json:"last_click"`
|
||||
}
|
||||
|
||||
type FacebookLikes struct {
|
||||
RecipientLikes int `json:"recipient_likes"`
|
||||
UniqueLikes int `json:"unique_likes"`
|
||||
FacebookLikes int `json:"facebook_likes"`
|
||||
}
|
||||
|
||||
type IndustryStats struct {
|
||||
Type string `json:"type"`
|
||||
OpenRate float64 `json:"open_rate"`
|
||||
ClickRate float64 `json:"click_rate"`
|
||||
BounceRate float64 `json:"bounce_rate"`
|
||||
UnopenRate float64 `json:"unopen_rate"`
|
||||
UnsubRate float64 `json:"unsub_rate"`
|
||||
AbuseRate float64 `json:"abuse_rate"`
|
||||
}
|
||||
|
||||
type ListStats struct {
|
||||
SubRate float64 `json:"sub_rate"`
|
||||
UnsubRate float64 `json:"unsub_rate"`
|
||||
OpenRate float64 `json:"open_rate"`
|
||||
ClickRate float64 `json:"click_rate"`
|
||||
}
|
||||
|
||||
type TimeSerie struct {
|
||||
TimeStamp string `json:"timestamp"`
|
||||
EmailsSent int `json:"emails_sent"`
|
||||
UniqueOpens int `json:"unique_opens"`
|
||||
RecipientsClick int `json:"recipients_click"`
|
||||
}
|
||||
Reference in New Issue
Block a user