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 }