1
0
mirror of https://github.com/nikoksr/notify.git synced 2025-07-15 01:34:58 +02:00

fmt/linter ran in correct order

This commit is contained in:
gtourkas
2021-03-21 18:09:47 +02:00
parent d61e3712f5
commit 5dbd63751f
3 changed files with 112 additions and 113 deletions

View File

@ -27,7 +27,7 @@ test:
# gofumports and gci all go files # gofumports and gci all go files
fmt: 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 . gci -w -local github.com/nikoksr/notify .
.PHONY: fmt .PHONY: fmt

View File

@ -1,58 +1,56 @@
package wechat package wechat
import ( import (
"context" "context"
"fmt" "fmt"
"github.com/pkg/errors" "net/http"
"github.com/silenceper/wechat/v2" "sync"
"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"
)
"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. // Config is the Service configuration.
type Config struct { type Config struct {
AppID string AppID string
AppSecret string AppSecret string
Token string Token string
EncodingAESKey string EncodingAESKey string
} }
// wechatMessageManager abstracts go-wechat's message.Manager for writing unit tests // wechatMessageManager abstracts go-wechat's message.Manager for writing unit tests
type wechatMessageManager interface { 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. // Service encapsulates the WeChat client along with internal state for storing users.
type Service struct { type Service struct {
config Config config Config
messageManager wechatMessageManager messageManager wechatMessageManager
userIDs []string userIDs []string
} }
// New returns a new instance of a WeChat notification service. // New returns a new instance of a WeChat notification service.
func New(cfg Config) *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() oa := wc.GetOfficialAccount(wcCfg)
wcCfg := &config.Config{
AppID: cfg.AppID,
AppSecret: cfg.AppSecret,
Token: cfg.Token,
EncodingAESKey: cfg.EncodingAESKey,
Cache: cache.NewMemory(),
}
oa := wc.GetOfficialAccount(wcCfg) return &Service{
config: cfg,
return &Service{ messageManager: oa.GetCustomerMessageManager(),
config: cfg, }
messageManager: oa.GetCustomerMessageManager(),
}
} }
// WaitForOneOffVerification waits for the verification call from the WeChat backend. // 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 // See https://developers.weixin.qq.com/doc/offiaccount/en/Basic_Information/Access_Overview.html
func (s *Service) WaitForOneOffVerification( func (s *Service) WaitForOneOffVerification(
addr string, addr string,
devMode bool, devMode bool,
callback func(r *http.Request, verified bool)) error { callback func(r *http.Request, verified bool)) error {
srv := &http.Server{Addr: addr}
verificationDone := &sync.WaitGroup{}
verificationDone.Add(1)
srv := &http.Server{Addr: addr} http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
verificationDone := &sync.WaitGroup{} query := r.URL.Query()
verificationDone.Add(1)
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { echoStr := query.Get("echostr")
query := r.URL.Query() if devMode {
if callback != nil {
callback(r, true)
}
_, _ = w.Write([]byte(echoStr))
// verification done; dev mode
verificationDone.Done()
return
}
echoStr := query.Get("echostr") // perform signature check
if devMode { timestamp := query.Get("timestamp")
if callback != nil { nonce := query.Get("nonce")
callback(r, true) suppliedSignature := query.Get("signature")
} computedSignature := util.Signature(s.config.Token, timestamp, nonce)
w.Write([]byte(echoStr)) if suppliedSignature == computedSignature {
// verification done; dev mode if callback != nil {
verificationDone.Done() callback(r, true)
return }
} else { _, _ = w.Write([]byte(echoStr))
// perform signature check // verification done; prod mode
timestamp := query.Get("timestamp") verificationDone.Done()
nonce := query.Get("nonce") return
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)
}
})
var err error // verification not done (keep waiting)
go func() { if callback != nil {
if innerErr := srv.ListenAndServe(); innerErr != http.ErrServerClosed { callback(r, false)
err = errors.Wrapf(innerErr, "failed to wait for verification at '%s'", addr) }
} })
}()
// wait until verification is done and shutdown the server var err error
verificationDone.Wait() 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 // AddReceivers takes user ids and adds them to the internal users list. The Send method will send
// a given message to all those users. // a given message to all those users.
func (s *Service) AddReceivers(userIDs ...string) { 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. // 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 { 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 { return nil
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
} }

View File

@ -1,11 +1,12 @@
package wechat package wechat
import ( import (
"context" "context"
"github.com/silenceper/wechat/v2/officialaccount/message"
"github.com/pkg/errors"
"github.com/stretchr/testify/require"
"testing" "testing"
"github.com/pkg/errors"
"github.com/silenceper/wechat/v2/officialaccount/message"
"github.com/stretchr/testify/require"
) )
func TestAddReceivers(t *testing.T) { func TestAddReceivers(t *testing.T) {
@ -24,29 +25,29 @@ func TestSend(t *testing.T) {
assert := require.New(t) assert := require.New(t)
svc := &Service{ svc := &Service{
userIDs: []string{}, userIDs: []string{},
} }
// test wechat message manager returning error // test wechat message manager returning error
mockMsgManager := new(mockWechatMessageManager) mockMsgManager := new(mockWechatMessageManager)
mockMsgManager.On("Send", message.NewCustomerTextMessage("UserID1", "subject\nmessage")). mockMsgManager.On("Send", message.NewCustomerTextMessage("UserID1", "subject\nmessage")).
Return(errors.New("some error")) Return(errors.New("some error"))
svc.messageManager = mockMsgManager svc.messageManager = mockMsgManager
svc.AddReceivers("UserID1") svc.AddReceivers("UserID1")
ctx := context.Background() ctx := context.Background()
err := svc.Send(ctx, "subject", "message") err := svc.Send(ctx, "subject", "message")
assert.NotNil(err) assert.NotNil(err)
mockMsgManager.AssertExpectations(t) mockMsgManager.AssertExpectations(t)
// test success and multiple receivers // test success and multiple receivers
mockMsgManager = new(mockWechatMessageManager) mockMsgManager = new(mockWechatMessageManager)
mockMsgManager.On("Send", message.NewCustomerTextMessage("UserID1", "subject\nmessage")). mockMsgManager.On("Send", message.NewCustomerTextMessage("UserID1", "subject\nmessage")).
Return(nil) Return(nil)
mockMsgManager.On("Send", message.NewCustomerTextMessage("UserID2", "subject\nmessage")). mockMsgManager.On("Send", message.NewCustomerTextMessage("UserID2", "subject\nmessage")).
Return(nil) Return(nil)
svc.messageManager = mockMsgManager svc.messageManager = mockMsgManager
svc.AddReceivers("UserID1", "UserID2") svc.AddReceivers("UserID1", "UserID2")
err = svc.Send(ctx, "subject", "message") err = svc.Send(ctx, "subject", "message")
assert.Nil(err) assert.Nil(err)
mockMsgManager.AssertExpectations(t) mockMsgManager.AssertExpectations(t)
} }