forked from angelorc/mc-subscriber
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathserver.go
120 lines (99 loc) · 2.59 KB
/
server.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
package server
import (
"context"
"fmt"
"github.com/angelorc/mc-subscriber/config"
_ "github.com/angelorc/mc-subscriber/swagger"
"github.com/hanzoai/gochimp3"
"github.com/labstack/echo/v4"
"github.com/labstack/echo/v4/middleware"
echoSwagger "github.com/swaggo/echo-swagger"
"go.uber.org/zap"
"net/http"
"net/mail"
"strings"
"time"
)
type Server struct {
*echo.Echo
mc *config.MailchimpConfig
logger *zap.Logger
}
// @title BitSong -> Mailchimp subscriber
// @version 1.0
// @description The bitsong mailchimp subscriber proxy.
func NewServer(mc *config.MailchimpConfig, logger *zap.Logger) *Server {
e := echo.New()
e.HideBanner = true
e.HidePort = true
e.Debug = true
e.Use(middleware.Logger())
e.Use(middleware.Recover())
e.Use(middleware.CORS())
s := &Server{
Echo: e,
mc: mc,
logger: logger,
}
s.registerRoutes()
return s
}
func (s *Server) ShutdownWithTimeout(timeout time.Duration) error {
ctx, cancel := context.WithTimeout(context.Background(), timeout)
defer cancel()
return s.Shutdown(ctx)
}
func (s *Server) registerRoutes() {
s.POST("/subscribe", s.PostSubscribe)
s.GET("/swagger/*", echoSwagger.WrapHandler)
}
type PostResponse struct {
Status string `json:"status"`
}
type PostRequest struct {
Email string `json:"email"`
}
// PostSubscribe godoc
// @Summary Subsrcibe email.
// @Description Subscribe an email address.
// @Accept json
// @Produce json
// @Success 200 {object} PostResponse
// @Param email body PostRequest true "Email address"
// @Router /subscribe [post]
func (s *Server) PostSubscribe(c echo.Context) error {
pr := new(PostRequest)
if err := c.Bind(pr); err != nil {
return echo.NewHTTPError(http.StatusBadRequest, err.Error())
}
email := strings.TrimSpace(pr.Email)
// TODO: improve check
ok := isValidEmail(email)
if !ok {
return echo.NewHTTPError(http.StatusBadRequest, "email not valid")
}
if err := s.subscribeEmail(email); err != nil {
return echo.NewHTTPError(http.StatusBadRequest, err.Error())
}
return c.JSON(http.StatusOK, &PostResponse{Status: "ok"})
}
func isValidEmail(email string) bool {
_, err := mail.ParseAddress(email)
return err == nil
}
func (s *Server) subscribeEmail(email string) error {
client := gochimp3.New(s.mc.APIKey)
client.Timeout = 10 * time.Second
req := &gochimp3.MemberRequest{
EmailAddress: email,
Status: "pending",
}
list, err := client.GetList(s.mc.ListID, nil)
if err != nil {
return fmt.Errorf("failed to get list %s", s.mc.ListID)
}
if _, err := list.CreateMember(req); err != nil {
return fmt.Errorf("failed to subscribe %s", req.EmailAddress)
}
return nil
}