diff --git a/matterhook/matterhook.go b/matterhook/matterhook.go new file mode 100644 index 00000000..2f299cbb --- /dev/null +++ b/matterhook/matterhook.go @@ -0,0 +1,121 @@ +package matterhook + +import ( + "bytes" + "encoding/json" + "fmt" + "github.com/gorilla/schema" + "io" + "io/ioutil" + "log" + "net/http" + "strconv" +) + +// OMessage for mattermost incoming webhook. (send to mattermost) +type OMessage struct { + Channel string `json:"channel,omitempty"` + IconURL string `json:"icon_url,omitempty"` + IconEmoji string `json:"icon_emoji,omitempty"` + UserName string `json:"username,omitempty"` + Text string `json:"text"` +} + +// IMessage for mattermost outgoing webhook. (received from mattermost) +type IMessage struct { + Token string `schema:"token"` + TeamID string `schema:"team_id"` + TeamDomain string `schema:"team_domain"` + ChannelID string `schema:"channel_id"` + ServiceID string `schema:"service_id"` + ChannelName string `schema:"channel_name"` + Timestamp string `schema:"timestamp"` + UserID string `schema:"user_id"` + UserName string `schema:"user_name"` + Text string `schema:"text"` + TriggerWord string `schema:"trigger_word"` +} + +// Client for Mattermost. +type Client struct { + url string + In chan IMessage + Out chan OMessage + Config +} + +type Config struct { + Port int +} + +// New Mattermost client. +func New(url string, config Config) *Client { + c := &Client{url: url, In: make(chan IMessage), Out: make(chan OMessage), Config: config} + log.Println(config.Port) + if c.Port == 0 { + c.Port = 9999 + } + 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://0.0.0.0:%v...\n", c.Port) + if err := http.ListenAndServe((":" + strconv.Itoa(c.Port)), mux); err != nil { + log.Fatal(err) + } +} + +// ServeHTTP implementation. +func (c *Client) ServeHTTP(w http.ResponseWriter, r *http.Request) { + msg := IMessage{} + err := r.ParseForm() + if err != nil { + log.Println(err) + http.NotFound(w, r) + return + } + defer r.Body.Close() + decoder := schema.NewDecoder() + err = decoder.Decode(&msg, r.PostForm) + if err != nil { + log.Println(err) + http.NotFound(w, r) + return + } + c.In <- msg +} + +// Receive returns an incoming message from mattermost outgoing webhooks URL. +func (c *Client) Receive() IMessage { + for { + select { + case msg := <-c.In: + return msg + } + } +} + +// Send sends a msg to mattermost incoming webhooks URL. +func (c *Client) Send(msg OMessage) error { + buf, err := json.Marshal(msg) + if err != nil { + return err + } + resp, err := http.Post(c.url, "application/json", bytes.NewReader(buf)) + if err != nil { + return err + } + defer resp.Body.Close() + + // Read entire body to completion to re-use keep-alive connections. + io.Copy(ioutil.Discard, resp.Body) + + if resp.StatusCode != 200 { + return fmt.Errorf("unexpected status code: %d", resp.StatusCode) + } + return nil +}