diff --git a/cmd/sendsms/go.mod b/cmd/sendsms/go.mod index f81d747..3a5a029 100644 --- a/cmd/sendsms/go.mod +++ b/cmd/sendsms/go.mod @@ -1,5 +1,8 @@ module example.com/sendsms -go 1.24.4 +go 1.24.6 -require github.com/joho/godotenv v1.5.1 +require ( + github.com/joho/godotenv v1.5.1 + github.com/therootcompany/golib/http/androidsmsgateway v0.0.0-20260223054429-c8f26aca7c6d +) diff --git a/cmd/sendsms/go.sum b/cmd/sendsms/go.sum index d61b19e..5263b69 100644 --- a/cmd/sendsms/go.sum +++ b/cmd/sendsms/go.sum @@ -1,2 +1,4 @@ github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0= github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4= +github.com/therootcompany/golib/http/androidsmsgateway v0.0.0-20260223054429-c8f26aca7c6d h1:jKf9QQUiGAHsrjkfpoo4FTQnFJu4UkDkPreZLll7tdE= +github.com/therootcompany/golib/http/androidsmsgateway v0.0.0-20260223054429-c8f26aca7c6d/go.mod h1:2O9+uXPc1VAJvveK9eqm9X4e4pTJmFWV6vtJa3sI/CA= diff --git a/cmd/sendsms/sendsms.go b/cmd/sendsms/main.go similarity index 97% rename from cmd/sendsms/sendsms.go rename to cmd/sendsms/main.go index eee91cc..682a8f9 100644 --- a/cmd/sendsms/sendsms.go +++ b/cmd/sendsms/main.go @@ -16,6 +16,7 @@ import ( "time" "github.com/joho/godotenv" + "github.com/therootcompany/golib/http/androidsmsgateway" ) type SMSSender interface { @@ -31,16 +32,6 @@ type SMSMessage struct { Text string } -type TextMessage struct { - Text string `json:"text"` -} - -type Payload struct { - TextMessage TextMessage `json:"textMessage"` - PhoneNumbers []string `json:"phoneNumbers"` - Priority int `json:"priority,omitempty"` -} - var ErrInvalidClockFormat = fmt.Errorf("invalid clock time, ex: '06:00 PM', '6pm', or '18:00' (space and case insensitive)") var ErrInvalidClockTime = fmt.Errorf("invalid hour or minute, for example '27:63 p' would not be valid") var ErrPhoneEmpty = fmt.Errorf("no phone number") @@ -90,11 +81,11 @@ func main() { _ = godotenv.Load("./.env") // note: we could also use twilio, or whatever - var sender SMSSender = &SMSGatewayForAndroid{ - baseURL: os.Getenv("SMSGW_BASEURL"), - username: os.Getenv("SMSGW_USERNAME"), - password: os.Getenv("SMSGW_PASSWORD"), - } + var sender SMSSender = androidsmsgateway.New( + os.Getenv("SMSGW_BASEURL"), + os.Getenv("SMSGW_USERNAME"), + os.Getenv("SMSGW_PASSWORD"), + ) if os.Getenv("SMSGW_BASEURL") == "" { fmt.Fprintf(os.Stderr, "\n%sError%s: SMSGW_BASEURL is not set\n", textErr, textReset) os.Exit(1) diff --git a/cmd/sendsms/smsgatewayforandroid.go b/http/androidsmsgateway/androidsmsgateway.go similarity index 57% rename from cmd/sendsms/smsgatewayforandroid.go rename to http/androidsmsgateway/androidsmsgateway.go index 046f8bf..87f2979 100644 --- a/cmd/sendsms/smsgatewayforandroid.go +++ b/http/androidsmsgateway/androidsmsgateway.go @@ -1,4 +1,4 @@ -package main +package androidsmsgateway import ( "bytes" @@ -9,24 +9,36 @@ import ( "strings" ) -type SMSGatewayForAndroid struct { +type AndroidSMSGateway struct { baseURL string username string password string } -func New(baseURL, username, password string) *SMSGatewayForAndroid { - return &SMSGatewayForAndroid{ +func New(baseURL, username, password string) *AndroidSMSGateway { + return &AndroidSMSGateway{ baseURL: baseURL, username: username, password: password, } } -func (s *SMSGatewayForAndroid) CurlString(number, message string) string { +type MessagePayload struct { + TextMessage struct { + Text string `json:"text"` + } `json:"textMessage"` + PhoneNumbers []string `json:"phoneNumbers"` + Priority int `json:"priority,omitempty"` +} + +func (s *AndroidSMSGateway) CurlString(number, message string) string { url := s.baseURL + "/messages" - payload := Payload{ - TextMessage: TextMessage{Text: message}, + payload := MessagePayload{ + TextMessage: struct { + Text string `json:"text"` + }{ + Text: message, + }, PhoneNumbers: []string{number}, Priority: 65, } @@ -42,15 +54,19 @@ func (s *SMSGatewayForAndroid) CurlString(number, message string) string { " --data-binary '" + escapedBody + "'" } -func (s *SMSGatewayForAndroid) Send(number, message string) error { +func (s *AndroidSMSGateway) Send(number, message string) error { number = cleanPhoneNumber(number) if len(number) == 0 { panic(fmt.Errorf("non-sanitized number '%s'", number)) } url := s.baseURL + "/messages" - payload := Payload{ - TextMessage: TextMessage{Text: message}, + payload := MessagePayload{ + TextMessage: struct { + Text string `json:"text"` + }{ + Text: message, + }, PhoneNumbers: []string{number}, Priority: 65, } @@ -75,10 +91,22 @@ func (s *SMSGatewayForAndroid) Send(number, message string) error { if resp.StatusCode < 200 || resp.StatusCode >= 300 { body, _ := io.ReadAll(resp.Body) - return fmt.Errorf("failed sending message to '%s': %d %s\n", + return fmt.Errorf("failed sending message to '%s': %d %s", number, resp.StatusCode, string(body), ) } return nil } + +// we're not just skipping symbols, +// we're also eliminating non-printing characters copied from HTML and such +func cleanPhoneNumber(raw string) string { + var cleaned strings.Builder + for i, char := range raw { + if (i == 0 && char == '+') || (char >= '0' && char <= '9') { + cleaned.WriteRune(char) + } + } + return cleaned.String() +} diff --git a/http/androidsmsgateway/go.mod b/http/androidsmsgateway/go.mod new file mode 100644 index 0000000..c7bd44b --- /dev/null +++ b/http/androidsmsgateway/go.mod @@ -0,0 +1,3 @@ +module github.com/therootcompany/golib/http/androidsmsgateway + +go 1.24.6