package messenger import ( "Yimaru-Backend/internal/domain" "context" "encoding/json" "errors" "fmt" "io" "net/http" "net/url" "time" afro "github.com/amanuelabay/afrosms-go" "github.com/twilio/twilio-go" twilioApi "github.com/twilio/twilio-go/rest/api/v2010" ) var ( ErrSMSProviderNotFound = errors.New("SMS Provider Not Found") ) // If the company id is valid, it is a company based notification else its a global notification (by the super admin) func (s *Service) SendSMS(ctx context.Context, receiverPhone, message string) error { var settingsList domain.SettingList switch settingsList.SMSProvider { case domain.AfroMessage: return s.SendAfroMessageSMSLatest(ctx, receiverPhone, message, nil) case domain.TwilioSms: return s.SendTwilioSMS(ctx, receiverPhone, message) default: return ErrSMSProviderNotFound } } func (s *Service) SendAfroMessageSMS(ctx context.Context, receiverPhone, message string) error { apiKey := s.config.AFRO_SMS_API_KEY senderName := s.config.AFRO_SMS_SENDER_NAME hostURL := s.config.ADRO_SMS_HOST_URL endpoint := "/api/send" // API endpoint has been updated // TODO: no need for package for the afro message operations (pretty simple stuff) request := afro.GetRequest(apiKey, endpoint, hostURL) request.BaseURL = "https://api.afromessage.com/api/send" request.Method = "GET" request.Sender(senderName) request.To(receiverPhone, message) response, err := afro.MakeRequestWithContext(ctx, request) if err != nil { return err } if response["acknowledge"] == "success" { return nil } else { fmt.Println(response["response"].(map[string]interface{})) return errors.New("SMS delivery failed") } } func (s *Service) SendAfroMessageSMSLatest( ctx context.Context, receiverPhone string, message string, callbackURL *string, // optional ) error { baseURL := s.config.AFROSMSConfig.AfroSMSBaseURL // Build query parameters explicitly params := url.Values{} params.Set("to", receiverPhone) params.Set("message", message) params.Set("sender", s.config.AFRO_SMS_SENDER_NAME) // Optional parameters if s.config.AFROSMSConfig.AfroSMSIdentifierID != "" { params.Set("from", s.config.AFROSMSConfig.AfroSMSIdentifierID) } if callbackURL != nil { params.Set("callback", *callbackURL) } // Construct full URL reqURL := fmt.Sprintf("%s?%s", baseURL, params.Encode()) req, err := http.NewRequestWithContext(ctx, http.MethodGet, reqURL, nil) if err != nil { return err } // AfroMessage authentication (API key) req.Header.Set("Authorization", "Bearer "+s.config.AFRO_SMS_API_KEY) req.Header.Set("Accept", "application/json") client := &http.Client{ Timeout: 10 * time.Second, } resp, err := client.Do(req) if err != nil { return err } defer resp.Body.Close() body, err := io.ReadAll(resp.Body) if err != nil { return err } if resp.StatusCode != http.StatusOK { return fmt.Errorf( "afromessage sms failed: status=%d response=%s", resp.StatusCode, string(body), ) } // Parse response var result map[string]interface{} if err := json.Unmarshal(body, &result); err != nil { return err } ack, ok := result["acknowledge"].(string) if !ok || ack != "success" { return fmt.Errorf("sms delivery failed: %v", result) } return nil } func (s *Service) SendTwilioSMS(ctx context.Context, receiverPhone, message string) error { accountSid := s.config.TwilioAccountSid authToken := s.config.TwilioAuthToken senderPhone := s.config.TwilioSenderPhoneNumber client := twilio.NewRestClientWithParams(twilio.ClientParams{ Username: accountSid, Password: authToken, }) params := &twilioApi.CreateMessageParams{} params.SetTo(receiverPhone) params.SetFrom(senderPhone) params.SetBody(message) _, err := client.Api.CreateMessage(params) if err != nil { return fmt.Errorf("%s", "Error sending SMS message: %s"+err.Error()) } return nil }