xmpp-webhook

webhook to xmpp gateway (clone of https://github.com/opthomas-prime/xmpp-webhook/ with my own mods)
git clone https://git.e1e0.net/xmpp-webhook.git
Log | Files | Refs | README | LICENSE

main.go (4007B)


      1 package main
      2 
      3 import (
      4 	"flag"
      5 	"fmt"
      6 	"log"
      7 	"net/http"
      8 	"os"
      9 	"regexp"
     10 	"strings"
     11 
     12 	"github.com/emgee/go-xmpp/src/xmpp"
     13 )
     14 
     15 var (
     16 	Version   string
     17 	Build     string
     18 	BuildDate string
     19 )
     20 
     21 // starts xmpp session and returns the xmpp client
     22 func xmppLogin(id string, pass string) (*xmpp.XMPP, error) {
     23 	// parse jid structure
     24 	jid, err := xmpp.ParseJID(id)
     25 	if err != nil {
     26 		return nil, err
     27 	}
     28 
     29 	// extract/generate address:port from jid
     30 	addr, err := xmpp.HomeServerAddrs(jid)
     31 	if err != nil {
     32 		return nil, err
     33 	}
     34 
     35 	// create xml stream to address
     36 	stream, err := xmpp.NewStream(addr[0], nil)
     37 	if err != nil {
     38 		return nil, err
     39 	}
     40 
     41 	// create client (login)
     42 	client, err := xmpp.NewClientXMPP(stream, jid, pass, nil)
     43 	if err != nil {
     44 		return nil, err
     45 	}
     46 
     47 	return client, nil
     48 }
     49 
     50 func main() {
     51 	verF := flag.Bool("version", false, "Prints version and exit")
     52 	flag.Parse()
     53 
     54 	if *verF {
     55 		fmt.Printf("xmpp-webhook v%s, built on: %s\n", Version, BuildDate)
     56 		fmt.Printf("Git rev: %s\n", Build)
     57 		os.Exit(0)
     58 	}
     59 
     60 	// get xmpp credentials and message receivers from env
     61 	xi := os.Getenv("XMPP_ID")
     62 	xp := os.Getenv("XMPP_PASS")
     63 	xr := os.Getenv("XMPP_RECEIVERS")
     64 	port := os.Getenv("XMPP_HOOK_PORT")
     65 	flagsFolder := os.Getenv("XMPP_HOOK_FLAGS_FOLDER")
     66 
     67 	// check if xmpp credentials and receiver list are supplied
     68 	if len(xi) < 1 || len(xp) < 1 || len(xr) < 1 {
     69 		log.Fatal("XMPP_ID, XMPP_PASS or XMPP_RECEIVERS not set")
     70 	}
     71 
     72 	if len(port) < 1 {
     73 		port = "4321"
     74 	}
     75 
     76 	if len(flagsFolder) < 1 {
     77 		flagsFolder = "/tmp/xmpp_flags"
     78 	}
     79 
     80 	// connect to xmpp server
     81 	xc, err := xmppLogin(xi, xp)
     82 	if err != nil {
     83 		log.Fatal(err)
     84 	}
     85 
     86 	// announce initial presence
     87 	xc.Out <- xmpp.Presence{}
     88 
     89 	// listen for incoming xmpp stanzas
     90 	go func() {
     91 		for stanza := range xc.In {
     92 			// check if stanza is a message
     93 			m, ok := stanza.(*xmpp.Message)
     94 			if ok && len(m.Body) > 0 {
     95 				/* echo the message only if it's from me
     96 				   get first the id from the full From and then check if it's on
     97 				   the list of XMPP_RECEIVERS */
     98 				fromId := strings.Split(m.From, "/")
     99 				if strings.Contains(xr, fromId[0]) {
    100 					mybody := "Parsing command ..."
    101 					xc.Out <- xmpp.Message{
    102 						To:   m.From,
    103 						Body: []xmpp.MessageBody{{Value: mybody}},
    104 						Type: "chat",
    105 					}
    106 					if err := parseMessage(m.Body, flagsFolder); err != nil {
    107 						mybody = err.Error()
    108 					} else {
    109 						mybody = "Command executed"
    110 					}
    111 					xc.Out <- xmpp.Message{
    112 						To:   m.From,
    113 						Body: []xmpp.MessageBody{{Value: mybody}},
    114 						Type: "chat",
    115 					}
    116 				} else {
    117 					log.Printf("%s tried to contact and is not on XMPP_RECEIVERS\n", m.From)
    118 				}
    119 			}
    120 		}
    121 		// xc.In is closed when the server closes the stream
    122 		log.Fatal("connection lost")
    123 	}()
    124 
    125 	// create chan for messages (webhooks -> xmpp)
    126 	messages := make(chan string)
    127 
    128 	// wait for messages from the webhooks and send them to all receivers
    129 	go func() {
    130 		for m := range messages {
    131 			for _, r := range strings.Split(xr, ",") {
    132 				re := regexp.MustCompile(`AC:\d{4}`)
    133 				alertCode := re.FindString(m)
    134 				if len(alertCode) > 0 {
    135 					log.Printf("Found alert code %s", alertCode)
    136 					if err := createFolder(flagsFolder); err != nil {
    137 						m = m + "\n" + err.Error()
    138 						log.Printf("ERROR: %s", err.Error())
    139 					}
    140 					err = writeFileFlag(flagsFolder+"/"+alertCode, alertCode)
    141 					if err != nil {
    142 						m = m + "\n" + err.Error()
    143 						log.Printf("ERROR (on file creation): %s", err.Error())
    144 					}
    145 				}
    146 				xc.Out <- xmpp.Message{
    147 					To: r,
    148 					Body: []xmpp.MessageBody{
    149 						{
    150 							Value: m,
    151 						},
    152 					},
    153 					Type: "chat",
    154 				}
    155 			}
    156 		}
    157 	}()
    158 
    159 	// initialize handler for grafana alerts
    160 	http.Handle("/grafana", newMessageHandler(messages, grafanaParserFunc))
    161 
    162 	// initialize handler for custom alerts
    163 	http.Handle("/prometheus", newMessageHandler(messages, prometheusParserFunc))
    164 
    165 	// initialize handler for custom alerts
    166 	http.Handle("/custom", newMessageHandler(messages, customParserFunc))
    167 
    168 	// listen for requests
    169 	http.ListenAndServe(":"+port, nil)
    170 }