mirror of
https://github.com/nikoksr/notify.git
synced 2024-11-24 08:22:18 +02:00
fmt/linter ran in correct order
This commit is contained in:
parent
d61e3712f5
commit
5dbd63751f
2
Makefile
2
Makefile
@ -27,7 +27,7 @@ test:
|
||||
|
||||
# gofumports and gci all go files
|
||||
fmt:
|
||||
find . -name '*.go' -not -wholename './vendor/*' | while read -r file; do gofumports -w "$$file"; done
|
||||
find . -name '*.go' -not -wholename './vendor/*' | while read -r file; do gofumpt -w "$$file"; done
|
||||
gci -w -local github.com/nikoksr/notify .
|
||||
.PHONY: fmt
|
||||
|
||||
|
@ -1,58 +1,56 @@
|
||||
package wechat
|
||||
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/silenceper/wechat/v2"
|
||||
"github.com/silenceper/wechat/v2/cache"
|
||||
"github.com/silenceper/wechat/v2/officialaccount/config"
|
||||
"github.com/silenceper/wechat/v2/officialaccount/message"
|
||||
"github.com/silenceper/wechat/v2/util"
|
||||
"net/http"
|
||||
"sync"
|
||||
)
|
||||
"context"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"sync"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/silenceper/wechat/v2"
|
||||
"github.com/silenceper/wechat/v2/cache"
|
||||
"github.com/silenceper/wechat/v2/officialaccount/config"
|
||||
"github.com/silenceper/wechat/v2/officialaccount/message"
|
||||
"github.com/silenceper/wechat/v2/util"
|
||||
)
|
||||
|
||||
// Config is the Service configuration.
|
||||
type Config struct {
|
||||
AppID string
|
||||
AppSecret string
|
||||
Token string
|
||||
EncodingAESKey string
|
||||
AppID string
|
||||
AppSecret string
|
||||
Token string
|
||||
EncodingAESKey string
|
||||
}
|
||||
|
||||
// wechatMessageManager abstracts go-wechat's message.Manager for writing unit tests
|
||||
type wechatMessageManager interface {
|
||||
Send(msg *message.CustomerMessage) error
|
||||
Send(msg *message.CustomerMessage) error
|
||||
}
|
||||
|
||||
// Service encapsulates the WeChat client along with internal state for storing users.
|
||||
type Service struct {
|
||||
config Config
|
||||
messageManager wechatMessageManager
|
||||
userIDs []string
|
||||
config Config
|
||||
messageManager wechatMessageManager
|
||||
userIDs []string
|
||||
}
|
||||
|
||||
// New returns a new instance of a WeChat notification service.
|
||||
func New(cfg Config) *Service {
|
||||
wc := wechat.NewWechat()
|
||||
wcCfg := &config.Config{
|
||||
AppID: cfg.AppID,
|
||||
AppSecret: cfg.AppSecret,
|
||||
Token: cfg.Token,
|
||||
EncodingAESKey: cfg.EncodingAESKey,
|
||||
Cache: cache.NewMemory(),
|
||||
}
|
||||
|
||||
wc := wechat.NewWechat()
|
||||
wcCfg := &config.Config{
|
||||
AppID: cfg.AppID,
|
||||
AppSecret: cfg.AppSecret,
|
||||
Token: cfg.Token,
|
||||
EncodingAESKey: cfg.EncodingAESKey,
|
||||
Cache: cache.NewMemory(),
|
||||
}
|
||||
oa := wc.GetOfficialAccount(wcCfg)
|
||||
|
||||
oa := wc.GetOfficialAccount(wcCfg)
|
||||
|
||||
return &Service{
|
||||
config: cfg,
|
||||
messageManager: oa.GetCustomerMessageManager(),
|
||||
}
|
||||
return &Service{
|
||||
config: cfg,
|
||||
messageManager: oa.GetCustomerMessageManager(),
|
||||
}
|
||||
}
|
||||
|
||||
// WaitForOneOffVerification waits for the verification call from the WeChat backend.
|
||||
@ -63,84 +61,84 @@ func New(cfg Config) *Service {
|
||||
//
|
||||
// See https://developers.weixin.qq.com/doc/offiaccount/en/Basic_Information/Access_Overview.html
|
||||
func (s *Service) WaitForOneOffVerification(
|
||||
addr string,
|
||||
devMode bool,
|
||||
callback func(r *http.Request, verified bool)) error {
|
||||
addr string,
|
||||
devMode bool,
|
||||
callback func(r *http.Request, verified bool)) error {
|
||||
srv := &http.Server{Addr: addr}
|
||||
verificationDone := &sync.WaitGroup{}
|
||||
verificationDone.Add(1)
|
||||
|
||||
srv := &http.Server{Addr: addr}
|
||||
verificationDone := &sync.WaitGroup{}
|
||||
verificationDone.Add(1)
|
||||
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
|
||||
query := r.URL.Query()
|
||||
|
||||
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
|
||||
query := r.URL.Query()
|
||||
echoStr := query.Get("echostr")
|
||||
if devMode {
|
||||
if callback != nil {
|
||||
callback(r, true)
|
||||
}
|
||||
_, _ = w.Write([]byte(echoStr))
|
||||
// verification done; dev mode
|
||||
verificationDone.Done()
|
||||
return
|
||||
}
|
||||
|
||||
echoStr := query.Get("echostr")
|
||||
if devMode {
|
||||
if callback != nil {
|
||||
callback(r, true)
|
||||
}
|
||||
w.Write([]byte(echoStr))
|
||||
// verification done; dev mode
|
||||
verificationDone.Done()
|
||||
return
|
||||
} else {
|
||||
// perform signature check
|
||||
timestamp := query.Get("timestamp")
|
||||
nonce := query.Get("nonce")
|
||||
suppliedSignature := query.Get("signature")
|
||||
computedSignature := util.Signature(s.config.Token, timestamp, nonce)
|
||||
if suppliedSignature == computedSignature {
|
||||
if callback != nil {
|
||||
callback(r, true)
|
||||
}
|
||||
w.Write([]byte(echoStr))
|
||||
// verification done; prod mode
|
||||
verificationDone.Done()
|
||||
return
|
||||
}
|
||||
}
|
||||
// verification not done (keep waiting)
|
||||
if callback != nil {
|
||||
callback(r, false)
|
||||
}
|
||||
})
|
||||
// perform signature check
|
||||
timestamp := query.Get("timestamp")
|
||||
nonce := query.Get("nonce")
|
||||
suppliedSignature := query.Get("signature")
|
||||
computedSignature := util.Signature(s.config.Token, timestamp, nonce)
|
||||
if suppliedSignature == computedSignature {
|
||||
if callback != nil {
|
||||
callback(r, true)
|
||||
}
|
||||
_, _ = w.Write([]byte(echoStr))
|
||||
// verification done; prod mode
|
||||
verificationDone.Done()
|
||||
return
|
||||
}
|
||||
|
||||
var err error
|
||||
go func() {
|
||||
if innerErr := srv.ListenAndServe(); innerErr != http.ErrServerClosed {
|
||||
err = errors.Wrapf(innerErr, "failed to wait for verification at '%s'", addr)
|
||||
}
|
||||
}()
|
||||
// verification not done (keep waiting)
|
||||
if callback != nil {
|
||||
callback(r, false)
|
||||
}
|
||||
})
|
||||
|
||||
// wait until verification is done and shutdown the server
|
||||
verificationDone.Wait()
|
||||
var err error
|
||||
go func() {
|
||||
if innerErr := srv.ListenAndServe(); innerErr != http.ErrServerClosed {
|
||||
err = errors.Wrapf(innerErr, "failed to start verification listener '%s'", addr)
|
||||
}
|
||||
}()
|
||||
|
||||
srv.Shutdown(context.TODO())
|
||||
// wait until verification is done and shutdown the server
|
||||
verificationDone.Wait()
|
||||
|
||||
return err
|
||||
if innerErr := srv.Shutdown(context.TODO()); innerErr != nil {
|
||||
err = errors.Wrap(innerErr, "failed to shutdown verification listerer")
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
// AddReceivers takes user ids and adds them to the internal users list. The Send method will send
|
||||
// a given message to all those users.
|
||||
func (s *Service) AddReceivers(userIDs ...string) {
|
||||
s.userIDs = append(s.userIDs, userIDs...)
|
||||
s.userIDs = append(s.userIDs, userIDs...)
|
||||
}
|
||||
|
||||
// Send takes a message subject and a message content and sends them to all previously set users.
|
||||
func (s *Service) Send(ctx context.Context, subject, content string) error {
|
||||
for _, userID := range s.userIDs {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return ctx.Err()
|
||||
default:
|
||||
text := fmt.Sprintf("%s\n%s", subject, content)
|
||||
if err := s.messageManager.Send(message.NewCustomerTextMessage(userID, text)); err != nil {
|
||||
return errors.Wrapf(err, "failed to send message to WeChat user '%s'", userID)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for _, userID := range s.userIDs {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return ctx.Err()
|
||||
default:
|
||||
text := fmt.Sprintf("%s\n%s", subject, content)
|
||||
if err := s.messageManager.Send(message.NewCustomerTextMessage(userID, text)); err != nil {
|
||||
return errors.Wrapf(err, "failed to send message to WeChat user '%s'", userID)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -1,11 +1,12 @@
|
||||
package wechat
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/silenceper/wechat/v2/officialaccount/message"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/stretchr/testify/require"
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/silenceper/wechat/v2/officialaccount/message"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestAddReceivers(t *testing.T) {
|
||||
@ -24,29 +25,29 @@ func TestSend(t *testing.T) {
|
||||
assert := require.New(t)
|
||||
|
||||
svc := &Service{
|
||||
userIDs: []string{},
|
||||
userIDs: []string{},
|
||||
}
|
||||
|
||||
// test wechat message manager returning error
|
||||
mockMsgManager := new(mockWechatMessageManager)
|
||||
mockMsgManager.On("Send", message.NewCustomerTextMessage("UserID1", "subject\nmessage")).
|
||||
Return(errors.New("some error"))
|
||||
svc.messageManager = mockMsgManager
|
||||
mockMsgManager.On("Send", message.NewCustomerTextMessage("UserID1", "subject\nmessage")).
|
||||
Return(errors.New("some error"))
|
||||
svc.messageManager = mockMsgManager
|
||||
svc.AddReceivers("UserID1")
|
||||
ctx := context.Background()
|
||||
err := svc.Send(ctx, "subject", "message")
|
||||
assert.NotNil(err)
|
||||
mockMsgManager.AssertExpectations(t)
|
||||
mockMsgManager.AssertExpectations(t)
|
||||
|
||||
// test success and multiple receivers
|
||||
mockMsgManager = new(mockWechatMessageManager)
|
||||
mockMsgManager.On("Send", message.NewCustomerTextMessage("UserID1", "subject\nmessage")).
|
||||
Return(nil)
|
||||
mockMsgManager.On("Send", message.NewCustomerTextMessage("UserID2", "subject\nmessage")).
|
||||
Return(nil)
|
||||
mockMsgManager = new(mockWechatMessageManager)
|
||||
mockMsgManager.On("Send", message.NewCustomerTextMessage("UserID1", "subject\nmessage")).
|
||||
Return(nil)
|
||||
mockMsgManager.On("Send", message.NewCustomerTextMessage("UserID2", "subject\nmessage")).
|
||||
Return(nil)
|
||||
svc.messageManager = mockMsgManager
|
||||
svc.AddReceivers("UserID1", "UserID2")
|
||||
err = svc.Send(ctx, "subject", "message")
|
||||
assert.Nil(err)
|
||||
mockMsgManager.AssertExpectations(t)
|
||||
mockMsgManager.AssertExpectations(t)
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user