mirror of
https://github.com/nikoksr/notify.git
synced 2024-11-24 08:22:18 +02:00
feat(service): Add Plivo service
Added support for Plivo as a backend service with unit tests and documentation. Signed-off-by: Prashanth Pai <mail@ppai.me>
This commit is contained in:
parent
77cea7b546
commit
67b2d011b8
@ -64,10 +64,11 @@ _ = notifier.Send(
|
||||
- *Discord*
|
||||
- *Email*
|
||||
- *Microsoft Teams*
|
||||
- *Slack*
|
||||
- *Twitter*
|
||||
- *Telegram*
|
||||
- *Plivo*
|
||||
- *Pushbullet*
|
||||
- *Slack*
|
||||
- *Telegram*
|
||||
- *Twitter*
|
||||
|
||||
## Roadmap <a id="roadmap"></a>
|
||||
|
||||
|
4
go.mod
4
go.mod
@ -9,9 +9,13 @@ require (
|
||||
github.com/dghubble/go-twitter v0.0.0-20201011215211-4b180d0cc78d
|
||||
github.com/dghubble/oauth1 v0.7.0
|
||||
github.com/go-telegram-bot-api/telegram-bot-api v4.6.4+incompatible
|
||||
github.com/google/go-querystring v1.0.0 // indirect
|
||||
github.com/jordan-wright/email v4.0.1-0.20210109023952-943e75fe5223+incompatible
|
||||
github.com/pkg/errors v0.9.1
|
||||
github.com/plivo/plivo-go v5.5.1+incompatible
|
||||
github.com/sirupsen/logrus v1.7.0 // indirect
|
||||
github.com/slack-go/slack v0.8.0
|
||||
github.com/stretchr/testify v1.7.0
|
||||
github.com/technoweenie/multipartstreamer v1.0.1 // indirect
|
||||
golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad // indirect
|
||||
golang.org/x/sync v0.0.0-20201207232520-09787c993a3a
|
||||
|
5
go.sum
5
go.sum
@ -29,10 +29,15 @@ github.com/jordan-wright/email v4.0.1-0.20210109023952-943e75fe5223+incompatible
|
||||
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/plivo/plivo-go v5.5.1+incompatible h1:LtZaUNHjSrNzBCHAe/IdDBnLGlyZB+WX18Dr+dnlVzE=
|
||||
github.com/plivo/plivo-go v5.5.1+incompatible/go.mod h1:OhnI9crdl6O+D94Lp1lvuwJoA3KUH39J6IM+j3HwCBE=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/sirupsen/logrus v1.7.0 h1:ShrD1U9pZB12TX0cVy0DtePoCH97K8EtX+mg7ZARUtM=
|
||||
github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
|
||||
github.com/slack-go/slack v0.8.0 h1:ANyLY5KHLV+MxLJDQum2IuHTLwbCbDtaWY405X1EU9U=
|
||||
github.com/slack-go/slack v0.8.0/go.mod h1:FGqNzJBmxIsZURAxh2a8D21AnOVvvXZvGligs4npPUM=
|
||||
github.com/stretchr/objx v0.1.0 h1:4G4v2dO3VZwixGIRoQ5Lfboy6nUhCyYzaqnIAPPhYs4=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
|
49
service/plivo/README.md
Normal file
49
service/plivo/README.md
Normal file
@ -0,0 +1,49 @@
|
||||
# Plivo
|
||||
|
||||
[![go.dev reference](https://img.shields.io/badge/go.dev-reference-007d9c?logo=go&logoColor=white&style=flat)](https://pkg.go.dev/github.com/nikoksr/notify/service/plivo)
|
||||
|
||||
## Prerequisites
|
||||
|
||||
You will need to have a [Plivo](https://www.plivo.com/) account and the
|
||||
following things:
|
||||
|
||||
1. `Auth ID` and `Auth Token` from Plivo [console](https://console.plivo.com/dashboard/).
|
||||
1. An active rented Plivo [phone number](https://console.plivo.com/active-phone-numbers/).
|
||||
|
||||
## Usage
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"log"
|
||||
|
||||
"github.com/nikoksr/notify"
|
||||
"github.com/nikoksr/notify/service/plivo"
|
||||
)
|
||||
|
||||
func main() {
|
||||
plivoSvc, err := plivo.New(
|
||||
&plivo.ClientOptions{
|
||||
AuthID: "<Your-Plivo-Auth-Id>",
|
||||
AuthToken: "<Your-Plivo-Auth-Token>",
|
||||
}, &plivo.MessageOptions{
|
||||
Source: "<Your-Plivo-Source-Number>",
|
||||
})
|
||||
if err != nil {
|
||||
log.Fatalf("plivo.New() failed: %s", err.Error())
|
||||
}
|
||||
|
||||
plivoSvc.AddReceivers("Destination1")
|
||||
|
||||
notifier := notify.New()
|
||||
notifier.UseServices(plivoSvc)
|
||||
|
||||
err = notifier.Send("subject", "message")
|
||||
if err != nil {
|
||||
log.Fatalf("notifier.Send() failed: %s", err.Error())
|
||||
}
|
||||
|
||||
log.Printf("notification sent")
|
||||
}
|
||||
```
|
41
service/plivo/doc.go
Normal file
41
service/plivo/doc.go
Normal file
@ -0,0 +1,41 @@
|
||||
/*
|
||||
Package plivo provides message notification integration for Plivo.
|
||||
|
||||
Usage:
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"log"
|
||||
|
||||
"github.com/nikoksr/notify"
|
||||
"github.com/nikoksr/notify/service/plivo"
|
||||
)
|
||||
|
||||
func main() {
|
||||
plivoSvc, err := plivo.New(
|
||||
&plivo.ClientOptions{
|
||||
AuthID: "<Your-Plivo-Auth-Id>",
|
||||
AuthToken: "<Your-Plivo-Auth-Token>",
|
||||
}, &plivo.MessageOptions{
|
||||
Source: "<Your-Plivo-Source-Number>",
|
||||
})
|
||||
if err != nil {
|
||||
log.Fatalf("plivo.New() failed: %s", err.Error())
|
||||
}
|
||||
|
||||
plivoSvc.AddReceivers("Destination1")
|
||||
|
||||
notifier := notify.New()
|
||||
notifier.UseServices(plivoSvc)
|
||||
|
||||
err = notifier.Send("subject", "message")
|
||||
if err != nil {
|
||||
log.Fatalf("notifier.Send() failed: %s", err.Error())
|
||||
}
|
||||
|
||||
log.Printf("notification sent")
|
||||
}
|
||||
|
||||
*/
|
||||
package plivo
|
36
service/plivo/mock_plivoMsgClient.go
Normal file
36
service/plivo/mock_plivoMsgClient.go
Normal file
@ -0,0 +1,36 @@
|
||||
// Code generated by mockery v0.0.0-dev. DO NOT EDIT.
|
||||
|
||||
package plivo
|
||||
|
||||
import (
|
||||
plivo "github.com/plivo/plivo-go"
|
||||
mock "github.com/stretchr/testify/mock"
|
||||
)
|
||||
|
||||
// mockPlivoMsgClient is an autogenerated mock type for the plivoMsgClient type
|
||||
type mockPlivoMsgClient struct {
|
||||
mock.Mock
|
||||
}
|
||||
|
||||
// Create provides a mock function with given fields: _a0
|
||||
func (_m *mockPlivoMsgClient) Create(_a0 plivo.MessageCreateParams) (*plivo.MessageCreateResponseBody, error) {
|
||||
ret := _m.Called(_a0)
|
||||
|
||||
var r0 *plivo.MessageCreateResponseBody
|
||||
if rf, ok := ret.Get(0).(func(plivo.MessageCreateParams) *plivo.MessageCreateResponseBody); ok {
|
||||
r0 = rf(_a0)
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).(*plivo.MessageCreateResponseBody)
|
||||
}
|
||||
}
|
||||
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(1).(func(plivo.MessageCreateParams) error); ok {
|
||||
r1 = rf(_a0)
|
||||
} else {
|
||||
r1 = ret.Error(1)
|
||||
}
|
||||
|
||||
return r0, r1
|
||||
}
|
102
service/plivo/plivo.go
Normal file
102
service/plivo/plivo.go
Normal file
@ -0,0 +1,102 @@
|
||||
package plivo
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
plivo "github.com/plivo/plivo-go"
|
||||
)
|
||||
|
||||
// ClientOptions allow you to configure a Plivo SDK client.
|
||||
type ClientOptions struct {
|
||||
AuthID string // If empty, env variable PLIVO_AUTH_ID will be used
|
||||
AuthToken string // If empty, env variable PLIVO_AUTH_TOKEN will be used
|
||||
|
||||
// Optional
|
||||
HTTPClient *http.Client // Bring Your Own Client
|
||||
}
|
||||
|
||||
// MessageOptions allow you to configure options for sending a message.
|
||||
type MessageOptions struct {
|
||||
Source string // a Plivo source phone number or a Plivo Powerpack UUID
|
||||
|
||||
// Optional
|
||||
CallbackURL string // URL to which status update callbacks for the message should be sent
|
||||
CallbackMethod string // The HTTP method to be used when calling CallbackURL - GET or POST(default)
|
||||
}
|
||||
|
||||
// plivoMsgClient abstracts Plivo SDK for writing unit tests
|
||||
type plivoMsgClient interface {
|
||||
Create(plivo.MessageCreateParams) (*plivo.MessageCreateResponseBody, error)
|
||||
}
|
||||
|
||||
// Service is a Plivo client
|
||||
type Service struct {
|
||||
client plivoMsgClient
|
||||
mopts MessageOptions
|
||||
destinations []string
|
||||
}
|
||||
|
||||
// New creates a new instance of plivo service.
|
||||
func New(cOpts *ClientOptions, mOpts *MessageOptions) (*Service, error) {
|
||||
if cOpts == nil {
|
||||
return nil, fmt.Errorf("client-options cannot be nil")
|
||||
}
|
||||
|
||||
if mOpts == nil {
|
||||
return nil, fmt.Errorf("message-options cannot be nil")
|
||||
}
|
||||
|
||||
if mOpts.Source == "" {
|
||||
return nil, fmt.Errorf("source cannot be empty")
|
||||
}
|
||||
|
||||
client, err := plivo.NewClient(
|
||||
cOpts.AuthID,
|
||||
cOpts.AuthToken,
|
||||
&plivo.ClientOptions{
|
||||
HttpClient: cOpts.HTTPClient,
|
||||
},
|
||||
)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("plivo.NewClient() failed: %w", err)
|
||||
}
|
||||
|
||||
return &Service{
|
||||
client: client.Messages,
|
||||
mopts: *mOpts,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// AddReceivers adds the given destination phone numbers to the notifier.
|
||||
func (s *Service) AddReceivers(phoneNumbers ...string) {
|
||||
s.destinations = append(s.destinations, phoneNumbers...)
|
||||
}
|
||||
|
||||
// Send sends a SMS via Plivo to all previously added receivers.
|
||||
func (s *Service) Send(subject, message string) error {
|
||||
text := subject + "\n" + message
|
||||
|
||||
var dst string
|
||||
switch len(s.destinations) {
|
||||
case 0:
|
||||
return fmt.Errorf("no receivers added")
|
||||
case 1:
|
||||
dst = s.destinations[0]
|
||||
default:
|
||||
// multiple destinations, use bulk message syntax
|
||||
// see: https://www.plivo.com/docs/sms/api/message#bulk-messaging
|
||||
dst = strings.Join(s.destinations, "<")
|
||||
}
|
||||
|
||||
_, err := s.client.Create(plivo.MessageCreateParams{
|
||||
Dst: dst,
|
||||
Text: text,
|
||||
Src: s.mopts.Source,
|
||||
URL: s.mopts.CallbackURL,
|
||||
Method: s.mopts.CallbackMethod,
|
||||
})
|
||||
|
||||
return err
|
||||
}
|
78
service/plivo/plivo_test.go
Normal file
78
service/plivo/plivo_test.go
Normal file
@ -0,0 +1,78 @@
|
||||
package plivo
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"testing"
|
||||
|
||||
plivo "github.com/plivo/plivo-go"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestNew(t *testing.T) {
|
||||
assert := require.New(t)
|
||||
|
||||
// nil ClientOptions
|
||||
svc, err := New(nil, &MessageOptions{})
|
||||
assert.NotNil(err)
|
||||
assert.Nil(svc)
|
||||
|
||||
// nil MessageOptions
|
||||
svc, err = New(&ClientOptions{}, nil)
|
||||
assert.NotNil(err)
|
||||
assert.Nil(svc)
|
||||
|
||||
// empty source
|
||||
svc, err = New(&ClientOptions{}, &MessageOptions{})
|
||||
assert.NotNil(err)
|
||||
assert.Nil(svc)
|
||||
|
||||
// success
|
||||
svc, err = New(&ClientOptions{}, &MessageOptions{Source: "12345"})
|
||||
assert.Nil(err)
|
||||
assert.NotNil(svc)
|
||||
}
|
||||
|
||||
func TestAddReceivers(t *testing.T) {
|
||||
assert := require.New(t)
|
||||
|
||||
svc, err := New(&ClientOptions{}, &MessageOptions{Source: "12345"})
|
||||
assert.Nil(err)
|
||||
assert.NotNil(svc)
|
||||
|
||||
nums := []string{"1", "2", "3", "4", "5"}
|
||||
svc.AddReceivers(nums...)
|
||||
|
||||
assert.Equal(svc.destinations, nums)
|
||||
}
|
||||
|
||||
func TestSend(t *testing.T) {
|
||||
assert := require.New(t)
|
||||
|
||||
svc, err := New(&ClientOptions{}, &MessageOptions{Source: "12345"})
|
||||
assert.Nil(err)
|
||||
assert.NotNil(svc)
|
||||
|
||||
// no receivers added
|
||||
err = svc.Send("message", "test")
|
||||
assert.NotNil(err)
|
||||
|
||||
// test plivo client returning error
|
||||
mockClient := new(mockPlivoMsgClient)
|
||||
mockClient.On("Create", plivo.MessageCreateParams{Src: "12345", Dst: "67890", Text: "message\ntest"}).
|
||||
Return(nil, errors.New("some error"))
|
||||
svc.client = mockClient
|
||||
svc.AddReceivers("67890")
|
||||
err = svc.Send("message", "test")
|
||||
assert.NotNil(err)
|
||||
mockClient.AssertExpectations(t)
|
||||
|
||||
// test success and multiple receivers
|
||||
mockClient = new(mockPlivoMsgClient)
|
||||
mockClient.On("Create", plivo.MessageCreateParams{Src: "12345", Dst: "67890<09876", Text: "message\ntest"}).
|
||||
Return(nil, nil)
|
||||
svc.client = mockClient
|
||||
svc.AddReceivers("09876")
|
||||
err = svc.Send("message", "test")
|
||||
assert.Nil(err)
|
||||
mockClient.AssertExpectations(t)
|
||||
}
|
Loading…
Reference in New Issue
Block a user