service/plivo/plivo.go
package plivo
import (
"context"
"errors"
"fmt"
"net/http"
"strings"
plivo "github.com/plivo/plivo-go/v7"
)
// 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, errors.New("client-options cannot be nil")
}
if mOpts == nil {
return nil, errors.New("message-options cannot be nil")
}
if mOpts.Source == "" {
return nil, errors.New("source cannot be empty")
}
client, err := plivo.NewClient(
cOpts.AuthID,
cOpts.AuthToken,
&plivo.ClientOptions{
HttpClient: cOpts.HTTPClient,
},
)
if err != nil {
return nil, 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(ctx context.Context, subject, message string) error {
text := subject + "\n" + message
var dst string
switch len(s.destinations) {
case 0:
return errors.New("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, "<")
}
select {
case <-ctx.Done():
return ctx.Err()
default:
_, err := s.client.Create(plivo.MessageCreateParams{
Dst: dst,
Text: text,
Src: s.mopts.Source,
URL: s.mopts.CallbackURL,
Method: s.mopts.CallbackMethod,
})
if err != nil {
return fmt.Errorf("send SMS to %q: %w", dst, err)
}
}
return nil
}