2018-12-04 05:57:11 +00:00
// Statping
2018-10-03 08:17:25 +00:00
// Copyright (C) 2018. Hunter Long and the project contributors
// Written by Hunter Long <info@socialeck.com> and the project contributors
//
2018-12-04 04:17:29 +00:00
// https://github.com/hunterlong/statping
2018-10-03 08:17:25 +00:00
//
// The licenses for most software and other practical works are designed
// to take away your freedom to share and change the works. By contrast,
// the GNU General Public License is intended to guarantee your freedom to
// share and change all versions of a program--to make sure it remains free
// software for all its users.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
package notifiers
import (
"bytes"
"fmt"
2018-12-04 04:17:29 +00:00
"github.com/hunterlong/statping/core/notifier"
"github.com/hunterlong/statping/types"
"github.com/hunterlong/statping/utils"
2018-10-03 08:17:25 +00:00
"io/ioutil"
"net/http"
"strings"
"time"
)
const (
2018-10-06 05:05:50 +00:00
webhookMethod = "webhook"
2018-10-03 08:17:25 +00:00
)
2018-10-06 05:00:40 +00:00
type webhooker struct {
2018-10-03 08:17:25 +00:00
* notifier . Notification
}
2018-10-06 05:00:40 +00:00
var webhook = & webhooker { & notifier . Notification {
2018-10-06 05:05:50 +00:00
Method : webhookMethod ,
2018-10-06 05:00:40 +00:00
Title : "HTTP webhooker" ,
2018-10-03 08:17:25 +00:00
Description : "Send a custom HTTP request to a specific URL with your own body, headers, and parameters" ,
Author : "Hunter Long" ,
AuthorUrl : "https://github.com/hunterlong" ,
2018-10-21 16:22:26 +00:00
Icon : "fas fa-code-branch" ,
2018-10-03 08:17:25 +00:00
Delay : time . Duration ( 1 * time . Second ) ,
Form : [ ] notifier . NotificationForm { {
Type : "text" ,
Title : "HTTP Endpoint" ,
Placeholder : "http://webhookurl.com/JW2MCP4SKQP" ,
SmallText : "Insert the URL for your HTTP Requests" ,
DbField : "Host" ,
Required : true ,
} , {
Type : "text" ,
Title : "HTTP Method" ,
Placeholder : "POST" ,
SmallText : "Choose a HTTP method for example: GET, POST, DELETE, or PATCH" ,
DbField : "Var1" ,
Required : true ,
} , {
Type : "textarea" ,
Title : "HTTP Body" ,
Placeholder : ` { "service_id": "%s.Id", "service_name": "%s.Name"} ` ,
2018-10-03 10:47:32 +00:00
SmallText : "Optional HTTP body for a POST request. You can insert variables into your body request.<br>%service.Id, %service.Name, %service.Online<br>%failure.Issue" ,
2018-10-03 08:17:25 +00:00
DbField : "Var2" ,
} , {
Type : "text" ,
Title : "Content Type" ,
Placeholder : ` application/json ` ,
SmallText : "Optional content type for example: application/json or text/plain" ,
DbField : "api_key" ,
} , {
Type : "text" ,
Title : "Header" ,
Placeholder : "Authorization=Token12345" ,
SmallText : "Optional Headers for request use format: KEY=Value,Key=Value" ,
DbField : "api_secret" ,
} ,
} } }
// DEFINE YOUR NOTIFICATION HERE.
func init ( ) {
err := notifier . AddNotifier ( webhook )
if err != nil {
panic ( err )
}
}
2018-10-06 05:00:40 +00:00
// Send will send a HTTP Post to the webhooker API. It accepts type: string
func ( w * webhooker ) Send ( msg interface { } ) error {
2018-11-10 03:42:32 +00:00
resp , err := w . sendHttpWebhook ( msg . ( string ) )
2018-10-03 10:47:32 +00:00
if err == nil {
resp . Body . Close ( )
}
2018-10-03 08:17:25 +00:00
return err
}
2018-10-06 05:00:40 +00:00
func ( w * webhooker ) Select ( ) * notifier . Notification {
2018-10-03 08:17:25 +00:00
return w . Notification
}
func replaceBodyText ( body string , s * types . Service , f * types . Failure ) string {
if s != nil {
body = strings . Replace ( body , "%service.Name" , s . Name , - 1 )
body = strings . Replace ( body , "%service.Id" , utils . ToString ( s . Id ) , - 1 )
2018-10-03 10:47:32 +00:00
body = strings . Replace ( body , "%service.Online" , utils . ToString ( s . Online ) , - 1 )
2018-10-03 08:17:25 +00:00
}
2018-11-10 03:42:32 +00:00
if strings . Contains ( body , "%failure.Issue" ) && f != nil {
2018-10-03 08:17:25 +00:00
body = strings . Replace ( body , "%failure.Issue" , f . Issue , - 1 )
}
return body
}
2018-11-10 03:42:32 +00:00
func ( w * webhooker ) sendHttpWebhook ( body string ) ( * http . Response , error ) {
2018-10-03 08:17:25 +00:00
utils . Log ( 1 , fmt . Sprintf ( "sending body: '%v' to %v as a %v request" , body , w . Host , w . Var1 ) )
client := new ( http . Client )
client . Timeout = time . Duration ( 10 * time . Second )
var buf * bytes . Buffer
buf = bytes . NewBuffer ( nil )
if w . Var2 != "" {
2018-11-10 03:42:32 +00:00
buf = bytes . NewBuffer ( [ ] byte ( body ) )
2018-10-03 08:17:25 +00:00
}
req , err := http . NewRequest ( w . Var1 , w . Host , buf )
if err != nil {
return nil , err
}
if w . ApiSecret != "" {
splitArray := strings . Split ( w . ApiSecret , "," )
for _ , a := range splitArray {
split := strings . Split ( a , "=" )
req . Header . Add ( split [ 0 ] , split [ 1 ] )
}
}
2018-10-11 09:25:16 +00:00
if w . ApiKey != "" {
req . Header . Add ( "Content-Type" , w . ApiKey )
2018-10-03 08:17:25 +00:00
}
2018-12-04 05:57:11 +00:00
req . Header . Set ( "User-Agent" , "Statping" )
2018-10-03 08:17:25 +00:00
resp , err := client . Do ( req )
if err != nil {
return nil , err
}
return resp , err
}
2018-10-06 05:00:40 +00:00
func ( w * webhooker ) OnTest ( ) error {
2018-10-03 08:17:25 +00:00
service := & types . Service {
Id : 1 ,
Name : "Interpol - All The Rage Back Home" ,
Domain : "https://www.youtube.com/watch?v=-u6DvRyyKGU" ,
ExpectedStatus : 200 ,
Interval : 30 ,
Type : "http" ,
Method : "GET" ,
Timeout : 20 ,
LastStatusCode : 404 ,
2018-11-07 07:53:39 +00:00
Expected : types . NewNullString ( "test example" ) ,
2018-10-03 08:17:25 +00:00
LastResponse : "<html>this is an example response</html>" ,
CreatedAt : time . Now ( ) . Add ( - 24 * time . Hour ) ,
}
body := replaceBodyText ( w . Var2 , service , nil )
2018-11-10 03:42:32 +00:00
resp , err := w . sendHttpWebhook ( body )
2018-10-03 08:17:25 +00:00
if err != nil {
return err
}
defer resp . Body . Close ( )
content , err := ioutil . ReadAll ( resp . Body )
utils . Log ( 1 , fmt . Sprintf ( "webhook notifier received: '%v'" , string ( content ) ) )
return err
}
// OnFailure will trigger failing service
2018-10-06 05:00:40 +00:00
func ( w * webhooker ) OnFailure ( s * types . Service , f * types . Failure ) {
2018-10-03 08:17:25 +00:00
msg := replaceBodyText ( w . Var2 , s , f )
2018-11-01 14:37:20 +00:00
w . AddQueue ( s . Id , msg )
2018-10-03 08:17:25 +00:00
w . Online = false
}
// OnSuccess will trigger successful service
2018-10-06 05:00:40 +00:00
func ( w * webhooker ) OnSuccess ( s * types . Service ) {
2018-10-03 08:17:25 +00:00
if ! w . Online {
2018-11-01 14:37:20 +00:00
w . ResetUniqueQueue ( s . Id )
2018-10-03 08:17:25 +00:00
msg := replaceBodyText ( w . Var2 , s , nil )
2018-11-01 14:37:20 +00:00
w . AddQueue ( s . Id , msg )
2018-10-03 08:17:25 +00:00
}
w . Online = true
}
// OnSave triggers when this notifier has been saved
2018-10-06 05:00:40 +00:00
func ( w * webhooker ) OnSave ( ) error {
2018-10-03 08:17:25 +00:00
return nil
}