github.com/yrj2011/jx-test-infra@v0.0.0-20190529031832-7a2065ee98eb/prow/slack/client.go (about)

     1  /*
     2  Copyright 2017 The Kubernetes Authors.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8      http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package slack
    18  
    19  import (
    20  	"errors"
    21  	"fmt"
    22  	"io/ioutil"
    23  	"net/http"
    24  	"net/url"
    25  	"strings"
    26  
    27  	"github.com/sirupsen/logrus"
    28  )
    29  
    30  type Logger interface {
    31  	Debugf(s string, v ...interface{})
    32  }
    33  
    34  // Client allows you to provide connection to Slack API Server
    35  // It contains a token that allows to authenticate connection to post and work with channels in the domain
    36  type Client struct {
    37  	// If logger is non-nil, log all method calls with it.
    38  	logger Logger
    39  
    40  	token string
    41  	fake  bool
    42  }
    43  
    44  const (
    45  	chatPostMessage = "https://slack.com/api/chat.postMessage"
    46  
    47  	botName      = "prow"
    48  	botIconEmoji = ":prow:"
    49  )
    50  
    51  // NewClient creates a slack client with an API token.
    52  func NewClient(token string) *Client {
    53  	return &Client{
    54  		logger: logrus.WithField("client", "slack"),
    55  		token:  token,
    56  	}
    57  }
    58  
    59  // NewFakeClient returns a client that takes no actions.
    60  func NewFakeClient() *Client {
    61  	return &Client{
    62  		fake: true,
    63  	}
    64  }
    65  
    66  func (sl *Client) log(methodName string, args ...interface{}) {
    67  	if sl.logger == nil {
    68  		return
    69  	}
    70  	var as []string
    71  	for _, arg := range args {
    72  		as = append(as, fmt.Sprintf("%v", arg))
    73  	}
    74  	sl.logger.Debugf("%s(%s)", methodName, strings.Join(as, ", "))
    75  }
    76  
    77  func (sl *Client) urlValues() *url.Values {
    78  	uv := url.Values{}
    79  	uv.Add("username", botName)
    80  	uv.Add("icon_emoji", botIconEmoji)
    81  	uv.Add("token", sl.token)
    82  	return &uv
    83  }
    84  
    85  func (sl *Client) postMessage(url string, uv *url.Values) ([]byte, error) {
    86  	resp, err := http.PostForm(url, *uv)
    87  	if err != nil {
    88  		return nil, err
    89  	}
    90  	defer resp.Body.Close()
    91  
    92  	if resp.StatusCode != 200 {
    93  		t, _ := ioutil.ReadAll(resp.Body)
    94  		return nil, errors.New(string(t))
    95  	}
    96  	t, _ := ioutil.ReadAll(resp.Body)
    97  	return t, nil
    98  }
    99  
   100  // WriteMessage adds text to channel
   101  func (sl *Client) WriteMessage(text, channel string) error {
   102  	sl.log("WriteMessage", text, channel)
   103  	if sl.fake {
   104  		return nil
   105  	}
   106  	var uv *url.Values = sl.urlValues()
   107  	uv.Add("channel", channel)
   108  	uv.Add("text", text)
   109  
   110  	_, err := sl.postMessage(chatPostMessage, uv)
   111  	return err
   112  }