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

108 lines
2.6 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 (
defaultTextLocalApiBase = "https://api.textlocal.in"
textLocalTemplateErrorCode = 80
)
type TextlocalProvider struct {
Config *conf.TextlocalProviderConfiguration
APIPath string
}
type TextlocalError struct {
Code int `json:"code"`
Message string `json:"message"`
}
type TextlocalResponse struct {
Status string `json:"status"`
Errors []TextlocalError `json:"errors"`
Messages []TextlocalMessage `json:"messages"`
}
type TextlocalMessage struct {
MessageID string `json:"id"`
}
// Creates a SmsProvider with the Textlocal Config
func NewTextlocalProvider(config conf.TextlocalProviderConfiguration) (SmsProvider, error) {
if err := config.Validate(); err != nil {
return nil, err
}
apiPath := defaultTextLocalApiBase + "/send"
return &TextlocalProvider{
Config: &config,
APIPath: apiPath,
}, nil
}
func (t *TextlocalProvider) 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 TextLocal", channel)
}
}
// Send an SMS containing the OTP with Textlocal's API
func (t *TextlocalProvider) SendSms(phone string, message string) (string, error) {
body := url.Values{
"sender": {t.Config.Sender},
"apikey": {t.Config.ApiKey},
"message": {message},
"numbers": {phone},
}
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")
res, err := client.Do(r)
if err != nil {
return "", err
}
defer utilities.SafeClose(res.Body)
resp := &TextlocalResponse{}
derr := json.NewDecoder(res.Body).Decode(resp)
if derr != nil {
return "", derr
}
messageID := ""
if resp.Status != "success" {
if len(resp.Messages) > 0 {
messageID = resp.Messages[0].MessageID
}
if len(resp.Errors) > 0 && resp.Errors[0].Code == textLocalTemplateErrorCode {
return messageID, fmt.Errorf("textlocal error: %v (code: %v) template message: %s", resp.Errors[0].Message, resp.Errors[0].Code, message)
}
return messageID, fmt.Errorf("textlocal error: %v (code: %v) message %s", resp.Errors[0].Message, resp.Errors[0].Code, messageID)
}
return messageID, nil
}
func (t *TextlocalProvider) VerifyOTP(phone, code string) error {
return fmt.Errorf("VerifyOTP is not supported for Textlocal")
}