summaryrefslogtreecommitdiffstats
path: root/hook/rockethook/rockethook.go
blob: eafd4f438e3a400a36129045cf8de2728e101921 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
package rockethook

import (
	"crypto/tls"
	"encoding/json"
	"io/ioutil"
	"log"
	"net"
	"net/http"
)

// Message for rocketchat outgoing webhook.
type Message struct {
	Token       string `json:"token"`
	ChannelID   string `json:"channel_id"`
	ChannelName string `json:"channel_name"`
	Timestamp   string `json:"timestamp"`
	UserID      string `json:"user_id"`
	UserName    string `json:"user_name"`
	Text        string `json:"text"`
}

// Client for Rocketchat.
type Client struct {
	In         chan Message
	httpclient *http.Client
	Config
}

// Config for client.
type Config struct {
	BindAddress        string // Address to listen on
	Token              string // Only allow this token from Rocketchat. (Allow everything when empty)
	InsecureSkipVerify bool   // disable certificate checking
}

// New Rocketchat client.
func New(url string, config Config) *Client {
	c := &Client{In: make(chan Message), Config: config}
	tr := &http.Transport{
		TLSClientConfig: &tls.Config{InsecureSkipVerify: config.InsecureSkipVerify},
	}
	c.httpclient = &http.Client{Transport: tr}
	_, _, err := net.SplitHostPort(c.BindAddress)
	if err != nil {
		log.Fatalf("incorrect bindaddress %s", c.BindAddress)
	}
	go c.StartServer()
	return c
}

// StartServer starts a webserver listening for incoming mattermost POSTS.
func (c *Client) StartServer() {
	mux := http.NewServeMux()
	mux.Handle("/", c)
	log.Printf("Listening on http://%v...\n", c.BindAddress)
	if err := http.ListenAndServe(c.BindAddress, mux); err != nil {
		log.Fatal(err)
	}
}

// ServeHTTP implementation.
func (c *Client) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	if r.Method != "POST" {
		log.Println("invalid " + r.Method + " connection from " + r.RemoteAddr)
		http.NotFound(w, r)
		return
	}
	msg := Message{}
	body, err := ioutil.ReadAll(r.Body)
	log.Println(string(body))
	if err != nil {
		log.Println(err)
		http.NotFound(w, r)
		return
	}
	defer r.Body.Close()
	err = json.Unmarshal(body, &msg)
	if err != nil {
		log.Println(err)
		http.NotFound(w, r)
		return
	}
	if msg.Token == "" {
		log.Println("no token from " + r.RemoteAddr)
		http.NotFound(w, r)
		return
	}
	msg.ChannelName = "#" + msg.ChannelName
	if c.Token != "" {
		if msg.Token != c.Token {
			log.Println("invalid token " + msg.Token + " from " + r.RemoteAddr)
			http.NotFound(w, r)
			return
		}
	}
	c.In <- msg
}

// Receive returns an incoming message from mattermost outgoing webhooks URL.
func (c *Client) Receive() Message {
	for {
		select {
		case msg := <-c.In:
			return msg
		}
	}
}