chatdesk-ui/auth_v2.169.0/internal/api/sms_provider/messagebird.go

116 lines
2.9 KiB
Go

package sms_provider
import (
"encoding/json"
"fmt"
"net/http"
"net/url"
"strings"
"github.com/supabase/auth/internal/conf"
"github.com/supabase/auth/internal/utilities"
)
const (
defaultMessagebirdApiBase = "https://rest.messagebird.com"
)
type MessagebirdProvider struct {
Config *conf.MessagebirdProviderConfiguration
APIPath string
}
type MessagebirdResponseRecipients struct {
TotalSentCount int `json:"totalSentCount"`
}
type MessagebirdResponse struct {
ID string `json:"id"`
Recipients MessagebirdResponseRecipients `json:"recipients"`
}
type MessagebirdError struct {
Code int `json:"code"`
Description string `json:"description"`
Parameter string `json:"parameter"`
}
type MessagebirdErrResponse struct {
Errors []MessagebirdError `json:"errors"`
}
func (t MessagebirdErrResponse) Error() string {
return t.Errors[0].Description
}
// Creates a SmsProvider with the Messagebird Config
func NewMessagebirdProvider(config conf.MessagebirdProviderConfiguration) (SmsProvider, error) {
if err := config.Validate(); err != nil {
return nil, err
}
apiPath := defaultMessagebirdApiBase + "/messages"
return &MessagebirdProvider{
Config: &config,
APIPath: apiPath,
}, nil
}
func (t *MessagebirdProvider) SendMessage(phone, message, channel, otp string) (string, error) {
switch channel {
case SMSProvider:
return t.SendSms(phone, message)
default:
return "", fmt.Errorf("channel type %q is not supported for Messagebird", channel)
}
}
// Send an SMS containing the OTP with Messagebird's API
func (t *MessagebirdProvider) SendSms(phone string, message string) (string, error) {
body := url.Values{
"originator": {t.Config.Originator},
"body": {message},
"recipients": {phone},
"type": {"sms"},
"datacoding": {"unicode"},
}
client := &http.Client{Timeout: defaultTimeout}
r, err := http.NewRequest("POST", t.APIPath, strings.NewReader(body.Encode()))
if err != nil {
return "", err
}
r.Header.Add("Content-Type", "application/x-www-form-urlencoded")
r.Header.Add("Authorization", "AccessKey "+t.Config.AccessKey)
res, err := client.Do(r)
if err != nil {
return "", err
}
if res.StatusCode == http.StatusBadRequest || res.StatusCode == http.StatusForbidden || res.StatusCode == http.StatusUnauthorized || res.StatusCode == http.StatusUnprocessableEntity {
resp := &MessagebirdErrResponse{}
if err := json.NewDecoder(res.Body).Decode(resp); err != nil {
return "", err
}
return "", resp
}
defer utilities.SafeClose(res.Body)
// validate sms status
resp := &MessagebirdResponse{}
derr := json.NewDecoder(res.Body).Decode(resp)
if derr != nil {
return "", derr
}
if resp.Recipients.TotalSentCount == 0 {
return "", fmt.Errorf("messagebird error: total sent count is 0")
}
return resp.ID, nil
}
func (t *MessagebirdProvider) VerifyOTP(phone, code string) error {
return fmt.Errorf("VerifyOTP is not supported for Messagebird")
}