2020-03-12 08:09:25 +00:00
package notifiers
2018-07-19 03:20:43 +00:00
import (
2020-06-06 00:36:39 +00:00
"encoding/base64"
2018-09-15 22:21:58 +00:00
"encoding/json"
"errors"
2018-07-19 03:20:43 +00:00
"fmt"
2020-03-09 18:17:55 +00:00
"github.com/statping/statping/types/failures"
2020-03-14 03:13:20 +00:00
"github.com/statping/statping/types/notifications"
"github.com/statping/statping/types/notifier"
2020-07-22 19:07:42 +00:00
"github.com/statping/statping/types/null"
2020-03-09 18:17:55 +00:00
"github.com/statping/statping/types/services"
"github.com/statping/statping/utils"
2018-07-19 03:20:43 +00:00
"net/url"
"strings"
"time"
)
2020-03-14 03:13:20 +00:00
var _ notifier . Notifier = ( * twilio ) ( nil )
2020-03-09 15:15:15 +00:00
2018-09-15 22:39:17 +00:00
type twilio struct {
2020-03-14 03:13:20 +00:00
* notifications . Notification
2018-07-19 03:20:43 +00:00
}
2020-03-14 03:13:20 +00:00
func ( t * twilio ) Select ( ) * notifications . Notification {
return t . Notification
}
2020-08-03 05:48:35 +00:00
func ( t * twilio ) Valid ( values notifications . Values ) error {
return nil
}
2020-03-14 03:13:20 +00:00
var Twilio = & twilio { & notifications . Notification {
2018-09-16 07:48:34 +00:00
Method : "twilio" ,
Title : "Twilio" ,
Description : "Receive SMS text messages directly to your cellphone when a service is offline. You can use a Twilio test account with limits. This notifier uses the <a href=\"https://www.twilio.com/docs/usage/api\">Twilio API</a>." ,
2018-09-15 01:18:21 +00:00
Author : "Hunter Long" ,
AuthorUrl : "https://github.com/hunterlong" ,
2018-11-01 14:37:20 +00:00
Icon : "far fa-comment-alt" ,
2018-09-15 01:18:21 +00:00
Delay : time . Duration ( 10 * time . Second ) ,
2020-07-22 19:07:42 +00:00
SuccessData : null . NewNullString ( "Your service '{{.Service.Name}}' is currently online!" ) ,
FailureData : null . NewNullString ( "Your service '{{.Service.Name}}' is currently offline!" ) ,
2020-06-15 04:46:28 +00:00
DataType : "text" ,
2020-03-17 03:13:07 +00:00
Limits : 15 ,
2020-03-14 03:13:20 +00:00
Form : [ ] notifications . NotificationForm { {
2018-09-12 04:14:22 +00:00
Type : "text" ,
2019-01-17 22:19:18 +00:00
Title : "Account SID" ,
Placeholder : "Insert your Twilio Account SID" ,
2018-09-12 04:14:22 +00:00
DbField : "api_key" ,
2018-09-27 01:49:21 +00:00
Required : true ,
2018-09-12 04:14:22 +00:00
} , {
Type : "text" ,
Title : "Account Token" ,
2018-09-16 07:48:34 +00:00
Placeholder : "Insert your Twilio Account Token" ,
2018-09-12 04:14:22 +00:00
DbField : "api_secret" ,
2018-09-27 01:49:21 +00:00
Required : true ,
2018-09-12 04:14:22 +00:00
} , {
2020-06-22 07:13:57 +00:00
Type : "number" ,
2018-09-12 04:14:22 +00:00
Title : "SMS to Phone Number" ,
2018-09-15 22:21:58 +00:00
Placeholder : "18555555555" ,
2018-09-12 04:14:22 +00:00
DbField : "Var1" ,
2018-09-27 01:49:21 +00:00
Required : true ,
2018-09-12 04:14:22 +00:00
} , {
2020-06-22 07:13:57 +00:00
Type : "number" ,
2018-09-12 04:14:22 +00:00
Title : "From Phone Number" ,
2018-09-15 22:21:58 +00:00
Placeholder : "18555555555" ,
2018-09-12 04:14:22 +00:00
DbField : "Var2" ,
2018-09-27 01:49:21 +00:00
Required : true ,
2018-09-12 04:14:22 +00:00
} } } ,
2018-07-19 03:20:43 +00:00
}
2018-09-15 22:39:17 +00:00
// Send will send a HTTP Post to the Twilio SMS API. It accepts type: string
2020-04-11 05:59:51 +00:00
func ( t * twilio ) sendMessage ( message string ) ( string , error ) {
2020-07-22 19:07:42 +00:00
twilioUrl := fmt . Sprintf ( "https://api.twilio.com/2010-04-01/Accounts/%s/Messages.json" , t . ApiKey . String )
2018-11-25 03:56:09 +00:00
2018-09-15 01:18:21 +00:00
v := url . Values { }
2020-07-22 19:07:42 +00:00
v . Set ( "To" , "+" + t . Var1 . String )
v . Set ( "From" , "+" + t . Var2 . String )
2018-09-15 01:18:21 +00:00
v . Set ( "Body" , message )
2020-05-14 03:09:32 +00:00
rb := strings . NewReader ( v . Encode ( ) )
2018-11-25 03:56:09 +00:00
2020-07-22 19:07:42 +00:00
authHeader := base64 . StdEncoding . EncodeToString ( [ ] byte ( fmt . Sprintf ( "%s:%s" , t . ApiKey . String , t . ApiSecret . String ) ) )
2020-05-14 03:09:32 +00:00
2020-05-20 06:41:50 +00:00
contents , _ , err := utils . HttpRequest ( twilioUrl , "POST" , "application/x-www-form-urlencoded" , [ ] string { "Authorization=Basic " + authHeader } , rb , 10 * time . Second , true , nil )
2018-09-27 01:49:21 +00:00
success , _ := twilioSuccess ( contents )
2018-09-15 22:21:58 +00:00
if ! success {
2018-09-27 01:49:21 +00:00
errorOut := twilioError ( contents )
2020-06-04 23:49:37 +00:00
if errorOut . Code == 0 {
return string ( contents ) , nil
}
out := fmt . Sprintf ( "Error code %v - %s" , errorOut . Code , errorOut . Message )
2020-04-11 05:59:51 +00:00
return string ( contents ) , errors . New ( out )
2018-09-15 22:21:58 +00:00
}
2020-04-11 05:59:51 +00:00
return string ( contents ) , err
2018-07-19 03:20:43 +00:00
}
2018-09-15 22:39:17 +00:00
// OnFailure will trigger failing service
2020-06-26 04:08:12 +00:00
func ( t * twilio ) OnFailure ( s services . Service , f failures . Failure ) ( string , error ) {
2020-07-22 19:07:42 +00:00
msg := ReplaceVars ( t . FailureData . String , s , f )
2020-06-15 07:46:27 +00:00
return t . sendMessage ( msg )
2018-07-19 03:20:43 +00:00
}
2018-09-15 22:39:17 +00:00
// OnSuccess will trigger successful service
2020-06-26 04:08:12 +00:00
func ( t * twilio ) OnSuccess ( s services . Service ) ( string , error ) {
2020-07-22 19:07:42 +00:00
msg := ReplaceVars ( t . SuccessData . String , s , failures . Failure { } )
2020-06-15 07:46:27 +00:00
return t . sendMessage ( msg )
2018-07-19 03:20:43 +00:00
}
2018-09-15 22:21:58 +00:00
2018-09-27 01:49:21 +00:00
// OnTest will test the Twilio SMS messaging
2020-04-11 05:59:51 +00:00
func ( t * twilio ) OnTest ( ) ( string , error ) {
2018-09-27 01:49:21 +00:00
msg := fmt . Sprintf ( "Testing the Twilio SMS Notifier" )
2020-03-23 02:50:30 +00:00
return t . sendMessage ( msg )
2018-09-27 01:49:21 +00:00
}
2020-06-21 06:52:07 +00:00
// OnSave will trigger when this notifier is saved
func ( t * twilio ) OnSave ( ) ( string , error ) {
return "" , nil
}
2018-10-06 05:03:10 +00:00
func twilioSuccess ( res [ ] byte ) ( bool , twilioResponse ) {
var obj twilioResponse
2018-09-15 22:21:58 +00:00
json . Unmarshal ( res , & obj )
if obj . Status == "queued" {
return true , obj
}
return false , obj
}
2018-10-06 05:03:10 +00:00
func twilioError ( res [ ] byte ) twilioErrorObj {
var obj twilioErrorObj
2018-09-27 01:49:21 +00:00
json . Unmarshal ( res , & obj )
return obj
}
2018-10-06 05:03:10 +00:00
type twilioErrorObj struct {
2018-09-27 01:49:21 +00:00
Code int ` json:"code" `
Message string ` json:"message" `
MoreInfo string ` json:"more_info" `
Status int ` json:"status" `
}
2018-10-06 05:03:10 +00:00
type twilioResponse struct {
2018-09-15 22:21:58 +00:00
Sid string ` json:"sid" `
DateCreated string ` json:"date_created" `
DateUpdated string ` json:"date_updated" `
DateSent interface { } ` json:"date_sent" `
AccountSid string ` json:"account_sid" `
To string ` json:"to" `
From string ` json:"from" `
MessagingServiceSid interface { } ` json:"messaging_service_sid" `
Body string ` json:"body" `
Status string ` json:"status" `
NumSegments string ` json:"num_segments" `
NumMedia string ` json:"num_media" `
Direction string ` json:"direction" `
APIVersion string ` json:"api_version" `
Price interface { } ` json:"price" `
PriceUnit string ` json:"price_unit" `
ErrorCode interface { } ` json:"error_code" `
ErrorMessage interface { } ` json:"error_message" `
URI string ` json:"uri" `
SubresourceUris struct {
Media string ` json:"media" `
} ` json:"subresource_uris" `
}