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 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162
|
package slack
import (
"context"
"fmt"
"log"
"net/http"
"net/url"
"os"
)
const (
// APIURL of the slack api.
APIURL = "https://slack.com/api/"
// WEBAPIURLFormat ...
WEBAPIURLFormat = "https://%s.slack.com/api/users.admin.%s?t=%d"
)
// httpClient defines the minimal interface needed for an http.Client to be implemented.
type httpClient interface {
Do(*http.Request) (*http.Response, error)
}
// ResponseMetadata holds pagination metadata
type ResponseMetadata struct {
Cursor string `json:"next_cursor"`
Messages []string `json:"messages"`
Warnings []string `json:"warnings"`
}
func (t *ResponseMetadata) initialize() *ResponseMetadata {
if t != nil {
return t
}
return &ResponseMetadata{}
}
// AuthTestResponse ...
type AuthTestResponse struct {
URL string `json:"url"`
Team string `json:"team"`
User string `json:"user"`
TeamID string `json:"team_id"`
UserID string `json:"user_id"`
// EnterpriseID is only returned when an enterprise id present
EnterpriseID string `json:"enterprise_id,omitempty"`
BotID string `json:"bot_id"`
}
type authTestResponseFull struct {
SlackResponse
AuthTestResponse
}
// Client for the slack api.
type ParamOption func(*url.Values)
type Client struct {
token string
appLevelToken string
endpoint string
debug bool
log ilogger
httpclient httpClient
}
// Option defines an option for a Client
type Option func(*Client)
// OptionHTTPClient - provide a custom http client to the slack client.
func OptionHTTPClient(client httpClient) func(*Client) {
return func(c *Client) {
c.httpclient = client
}
}
// OptionDebug enable debugging for the client
func OptionDebug(b bool) func(*Client) {
return func(c *Client) {
c.debug = b
}
}
// OptionLog set logging for client.
func OptionLog(l logger) func(*Client) {
return func(c *Client) {
c.log = internalLog{logger: l}
}
}
// OptionAPIURL set the url for the client. only useful for testing.
func OptionAPIURL(u string) func(*Client) {
return func(c *Client) { c.endpoint = u }
}
// OptionAppLevelToken sets an app-level token for the client.
func OptionAppLevelToken(token string) func(*Client) {
return func(c *Client) { c.appLevelToken = token }
}
// New builds a slack client from the provided token and options.
func New(token string, options ...Option) *Client {
s := &Client{
token: token,
endpoint: APIURL,
httpclient: &http.Client{},
log: log.New(os.Stderr, "slack-go/slack", log.LstdFlags|log.Lshortfile),
}
for _, opt := range options {
opt(s)
}
return s
}
// AuthTest tests if the user is able to do authenticated requests or not
func (api *Client) AuthTest() (response *AuthTestResponse, error error) {
return api.AuthTestContext(context.Background())
}
// AuthTestContext tests if the user is able to do authenticated requests or not with a custom context
func (api *Client) AuthTestContext(ctx context.Context) (response *AuthTestResponse, err error) {
api.Debugf("Challenging auth...")
responseFull := &authTestResponseFull{}
err = api.postMethod(ctx, "auth.test", url.Values{"token": {api.token}}, responseFull)
if err != nil {
return nil, err
}
return &responseFull.AuthTestResponse, responseFull.Err()
}
// Debugf print a formatted debug line.
func (api *Client) Debugf(format string, v ...interface{}) {
if api.debug {
api.log.Output(2, fmt.Sprintf(format, v...))
}
}
// Debugln print a debug line.
func (api *Client) Debugln(v ...interface{}) {
if api.debug {
api.log.Output(2, fmt.Sprintln(v...))
}
}
// Debug returns if debug is enabled.
func (api *Client) Debug() bool {
return api.debug
}
// post to a slack web method.
func (api *Client) postMethod(ctx context.Context, path string, values url.Values, intf interface{}) error {
return postForm(ctx, api.httpclient, api.endpoint+path, values, intf, api)
}
// get a slack web method.
func (api *Client) getMethod(ctx context.Context, path string, token string, values url.Values, intf interface{}) error {
return getResource(ctx, api.httpclient, api.endpoint+path, token, values, intf, api)
}
|