github.com/jfrerich/mattermost-server@v5.8.0-rc2+incompatible/model/client4.go (about)

     1  // Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved.
     2  // See License.txt for license information.
     3  
     4  package model
     5  
     6  import (
     7  	"bytes"
     8  	"encoding/json"
     9  	"fmt"
    10  	"io"
    11  	"io/ioutil"
    12  	"mime/multipart"
    13  	"net/http"
    14  	"net/url"
    15  	"strconv"
    16  	"strings"
    17  	"time"
    18  )
    19  
    20  const (
    21  	HEADER_REQUEST_ID         = "X-Request-ID"
    22  	HEADER_VERSION_ID         = "X-Version-ID"
    23  	HEADER_CLUSTER_ID         = "X-Cluster-ID"
    24  	HEADER_ETAG_SERVER        = "ETag"
    25  	HEADER_ETAG_CLIENT        = "If-None-Match"
    26  	HEADER_FORWARDED          = "X-Forwarded-For"
    27  	HEADER_REAL_IP            = "X-Real-IP"
    28  	HEADER_FORWARDED_PROTO    = "X-Forwarded-Proto"
    29  	HEADER_TOKEN              = "token"
    30  	HEADER_BEARER             = "BEARER"
    31  	HEADER_AUTH               = "Authorization"
    32  	HEADER_REQUESTED_WITH     = "X-Requested-With"
    33  	HEADER_REQUESTED_WITH_XML = "XMLHttpRequest"
    34  	STATUS                    = "status"
    35  	STATUS_OK                 = "OK"
    36  	STATUS_FAIL               = "FAIL"
    37  	STATUS_REMOVE             = "REMOVE"
    38  
    39  	CLIENT_DIR = "client"
    40  
    41  	API_URL_SUFFIX_V1 = "/api/v1"
    42  	API_URL_SUFFIX_V4 = "/api/v4"
    43  	API_URL_SUFFIX    = API_URL_SUFFIX_V4
    44  )
    45  
    46  type Response struct {
    47  	StatusCode    int
    48  	Error         *AppError
    49  	RequestId     string
    50  	Etag          string
    51  	ServerVersion string
    52  	Header        http.Header
    53  }
    54  
    55  type Client4 struct {
    56  	Url        string       // The location of the server, for example  "http://localhost:8065"
    57  	ApiUrl     string       // The api location of the server, for example "http://localhost:8065/api/v4"
    58  	HttpClient *http.Client // The http client
    59  	AuthToken  string
    60  	AuthType   string
    61  	HttpHeader map[string]string // Headers to be copied over for each request
    62  }
    63  
    64  func closeBody(r *http.Response) {
    65  	if r.Body != nil {
    66  		_, _ = ioutil.ReadAll(r.Body)
    67  		_ = r.Body.Close()
    68  	}
    69  }
    70  
    71  // Must is a convenience function used for testing.
    72  func (c *Client4) Must(result interface{}, resp *Response) interface{} {
    73  	if resp.Error != nil {
    74  		time.Sleep(time.Second)
    75  		panic(resp.Error)
    76  	}
    77  
    78  	return result
    79  }
    80  
    81  func NewAPIv4Client(url string) *Client4 {
    82  	return &Client4{url, url + API_URL_SUFFIX, &http.Client{}, "", "", map[string]string{}}
    83  }
    84  
    85  func BuildErrorResponse(r *http.Response, err *AppError) *Response {
    86  	var statusCode int
    87  	var header http.Header
    88  	if r != nil {
    89  		statusCode = r.StatusCode
    90  		header = r.Header
    91  	} else {
    92  		statusCode = 0
    93  		header = make(http.Header)
    94  	}
    95  
    96  	return &Response{
    97  		StatusCode: statusCode,
    98  		Error:      err,
    99  		Header:     header,
   100  	}
   101  }
   102  
   103  func BuildResponse(r *http.Response) *Response {
   104  	return &Response{
   105  		StatusCode:    r.StatusCode,
   106  		RequestId:     r.Header.Get(HEADER_REQUEST_ID),
   107  		Etag:          r.Header.Get(HEADER_ETAG_SERVER),
   108  		ServerVersion: r.Header.Get(HEADER_VERSION_ID),
   109  		Header:        r.Header,
   110  	}
   111  }
   112  
   113  func (c *Client4) MockSession(sessionToken string) {
   114  	c.AuthToken = sessionToken
   115  	c.AuthType = HEADER_BEARER
   116  }
   117  
   118  func (c *Client4) SetOAuthToken(token string) {
   119  	c.AuthToken = token
   120  	c.AuthType = HEADER_TOKEN
   121  }
   122  
   123  func (c *Client4) ClearOAuthToken() {
   124  	c.AuthToken = ""
   125  	c.AuthType = HEADER_BEARER
   126  }
   127  
   128  func (c *Client4) GetUsersRoute() string {
   129  	return fmt.Sprintf("/users")
   130  }
   131  
   132  func (c *Client4) GetUserRoute(userId string) string {
   133  	return fmt.Sprintf(c.GetUsersRoute()+"/%v", userId)
   134  }
   135  
   136  func (c *Client4) GetUserAccessTokensRoute() string {
   137  	return fmt.Sprintf(c.GetUsersRoute() + "/tokens")
   138  }
   139  
   140  func (c *Client4) GetUserAccessTokenRoute(tokenId string) string {
   141  	return fmt.Sprintf(c.GetUsersRoute()+"/tokens/%v", tokenId)
   142  }
   143  
   144  func (c *Client4) GetUserByUsernameRoute(userName string) string {
   145  	return fmt.Sprintf(c.GetUsersRoute()+"/username/%v", userName)
   146  }
   147  
   148  func (c *Client4) GetUserByEmailRoute(email string) string {
   149  	return fmt.Sprintf(c.GetUsersRoute()+"/email/%v", email)
   150  }
   151  
   152  func (c *Client4) GetTeamsRoute() string {
   153  	return fmt.Sprintf("/teams")
   154  }
   155  
   156  func (c *Client4) GetTeamRoute(teamId string) string {
   157  	return fmt.Sprintf(c.GetTeamsRoute()+"/%v", teamId)
   158  }
   159  
   160  func (c *Client4) GetTeamAutoCompleteCommandsRoute(teamId string) string {
   161  	return fmt.Sprintf(c.GetTeamsRoute()+"/%v/commands/autocomplete", teamId)
   162  }
   163  
   164  func (c *Client4) GetTeamByNameRoute(teamName string) string {
   165  	return fmt.Sprintf(c.GetTeamsRoute()+"/name/%v", teamName)
   166  }
   167  
   168  func (c *Client4) GetTeamMemberRoute(teamId, userId string) string {
   169  	return fmt.Sprintf(c.GetTeamRoute(teamId)+"/members/%v", userId)
   170  }
   171  
   172  func (c *Client4) GetTeamMembersRoute(teamId string) string {
   173  	return fmt.Sprintf(c.GetTeamRoute(teamId) + "/members")
   174  }
   175  
   176  func (c *Client4) GetTeamStatsRoute(teamId string) string {
   177  	return fmt.Sprintf(c.GetTeamRoute(teamId) + "/stats")
   178  }
   179  
   180  func (c *Client4) GetTeamImportRoute(teamId string) string {
   181  	return fmt.Sprintf(c.GetTeamRoute(teamId) + "/import")
   182  }
   183  
   184  func (c *Client4) GetChannelsRoute() string {
   185  	return fmt.Sprintf("/channels")
   186  }
   187  
   188  func (c *Client4) GetChannelsForTeamRoute(teamId string) string {
   189  	return fmt.Sprintf(c.GetTeamRoute(teamId) + "/channels")
   190  }
   191  
   192  func (c *Client4) GetChannelRoute(channelId string) string {
   193  	return fmt.Sprintf(c.GetChannelsRoute()+"/%v", channelId)
   194  }
   195  
   196  func (c *Client4) GetChannelByNameRoute(channelName, teamId string) string {
   197  	return fmt.Sprintf(c.GetTeamRoute(teamId)+"/channels/name/%v", channelName)
   198  }
   199  
   200  func (c *Client4) GetChannelByNameForTeamNameRoute(channelName, teamName string) string {
   201  	return fmt.Sprintf(c.GetTeamByNameRoute(teamName)+"/channels/name/%v", channelName)
   202  }
   203  
   204  func (c *Client4) GetChannelMembersRoute(channelId string) string {
   205  	return fmt.Sprintf(c.GetChannelRoute(channelId) + "/members")
   206  }
   207  
   208  func (c *Client4) GetChannelMemberRoute(channelId, userId string) string {
   209  	return fmt.Sprintf(c.GetChannelMembersRoute(channelId)+"/%v", userId)
   210  }
   211  
   212  func (c *Client4) GetPostsRoute() string {
   213  	return fmt.Sprintf("/posts")
   214  }
   215  
   216  func (c *Client4) GetPostsEphemeralRoute() string {
   217  	return fmt.Sprintf("/posts/ephemeral")
   218  }
   219  
   220  func (c *Client4) GetConfigRoute() string {
   221  	return fmt.Sprintf("/config")
   222  }
   223  
   224  func (c *Client4) GetLicenseRoute() string {
   225  	return fmt.Sprintf("/license")
   226  }
   227  
   228  func (c *Client4) GetPostRoute(postId string) string {
   229  	return fmt.Sprintf(c.GetPostsRoute()+"/%v", postId)
   230  }
   231  
   232  func (c *Client4) GetFilesRoute() string {
   233  	return fmt.Sprintf("/files")
   234  }
   235  
   236  func (c *Client4) GetFileRoute(fileId string) string {
   237  	return fmt.Sprintf(c.GetFilesRoute()+"/%v", fileId)
   238  }
   239  
   240  func (c *Client4) GetPluginsRoute() string {
   241  	return fmt.Sprintf("/plugins")
   242  }
   243  
   244  func (c *Client4) GetPluginRoute(pluginId string) string {
   245  	return fmt.Sprintf(c.GetPluginsRoute()+"/%v", pluginId)
   246  }
   247  
   248  func (c *Client4) GetSystemRoute() string {
   249  	return fmt.Sprintf("/system")
   250  }
   251  
   252  func (c *Client4) GetTestEmailRoute() string {
   253  	return fmt.Sprintf("/email/test")
   254  }
   255  
   256  func (c *Client4) GetTestS3Route() string {
   257  	return fmt.Sprintf("/file/s3_test")
   258  }
   259  
   260  func (c *Client4) GetDatabaseRoute() string {
   261  	return fmt.Sprintf("/database")
   262  }
   263  
   264  func (c *Client4) GetCacheRoute() string {
   265  	return fmt.Sprintf("/caches")
   266  }
   267  
   268  func (c *Client4) GetClusterRoute() string {
   269  	return fmt.Sprintf("/cluster")
   270  }
   271  
   272  func (c *Client4) GetIncomingWebhooksRoute() string {
   273  	return fmt.Sprintf("/hooks/incoming")
   274  }
   275  
   276  func (c *Client4) GetIncomingWebhookRoute(hookID string) string {
   277  	return fmt.Sprintf(c.GetIncomingWebhooksRoute()+"/%v", hookID)
   278  }
   279  
   280  func (c *Client4) GetComplianceReportsRoute() string {
   281  	return fmt.Sprintf("/compliance/reports")
   282  }
   283  
   284  func (c *Client4) GetComplianceReportRoute(reportId string) string {
   285  	return fmt.Sprintf("/compliance/reports/%v", reportId)
   286  }
   287  
   288  func (c *Client4) GetOutgoingWebhooksRoute() string {
   289  	return fmt.Sprintf("/hooks/outgoing")
   290  }
   291  
   292  func (c *Client4) GetOutgoingWebhookRoute(hookID string) string {
   293  	return fmt.Sprintf(c.GetOutgoingWebhooksRoute()+"/%v", hookID)
   294  }
   295  
   296  func (c *Client4) GetPreferencesRoute(userId string) string {
   297  	return fmt.Sprintf(c.GetUserRoute(userId) + "/preferences")
   298  }
   299  
   300  func (c *Client4) GetUserStatusRoute(userId string) string {
   301  	return fmt.Sprintf(c.GetUserRoute(userId) + "/status")
   302  }
   303  
   304  func (c *Client4) GetUserStatusesRoute() string {
   305  	return fmt.Sprintf(c.GetUsersRoute() + "/status")
   306  }
   307  
   308  func (c *Client4) GetSamlRoute() string {
   309  	return fmt.Sprintf("/saml")
   310  }
   311  
   312  func (c *Client4) GetLdapRoute() string {
   313  	return fmt.Sprintf("/ldap")
   314  }
   315  
   316  func (c *Client4) GetBrandRoute() string {
   317  	return fmt.Sprintf("/brand")
   318  }
   319  
   320  func (c *Client4) GetDataRetentionRoute() string {
   321  	return fmt.Sprintf("/data_retention")
   322  }
   323  
   324  func (c *Client4) GetElasticsearchRoute() string {
   325  	return fmt.Sprintf("/elasticsearch")
   326  }
   327  
   328  func (c *Client4) GetCommandsRoute() string {
   329  	return fmt.Sprintf("/commands")
   330  }
   331  
   332  func (c *Client4) GetCommandRoute(commandId string) string {
   333  	return fmt.Sprintf(c.GetCommandsRoute()+"/%v", commandId)
   334  }
   335  
   336  func (c *Client4) GetEmojisRoute() string {
   337  	return fmt.Sprintf("/emoji")
   338  }
   339  
   340  func (c *Client4) GetEmojiRoute(emojiId string) string {
   341  	return fmt.Sprintf(c.GetEmojisRoute()+"/%v", emojiId)
   342  }
   343  
   344  func (c *Client4) GetEmojiByNameRoute(name string) string {
   345  	return fmt.Sprintf(c.GetEmojisRoute()+"/name/%v", name)
   346  }
   347  
   348  func (c *Client4) GetReactionsRoute() string {
   349  	return fmt.Sprintf("/reactions")
   350  }
   351  
   352  func (c *Client4) GetOAuthAppsRoute() string {
   353  	return fmt.Sprintf("/oauth/apps")
   354  }
   355  
   356  func (c *Client4) GetOAuthAppRoute(appId string) string {
   357  	return fmt.Sprintf("/oauth/apps/%v", appId)
   358  }
   359  
   360  func (c *Client4) GetOpenGraphRoute() string {
   361  	return fmt.Sprintf("/opengraph")
   362  }
   363  
   364  func (c *Client4) GetJobsRoute() string {
   365  	return fmt.Sprintf("/jobs")
   366  }
   367  
   368  func (c *Client4) GetRolesRoute() string {
   369  	return fmt.Sprintf("/roles")
   370  }
   371  
   372  func (c *Client4) GetSchemesRoute() string {
   373  	return fmt.Sprintf("/schemes")
   374  }
   375  
   376  func (c *Client4) GetSchemeRoute(id string) string {
   377  	return c.GetSchemesRoute() + fmt.Sprintf("/%v", id)
   378  }
   379  
   380  func (c *Client4) GetAnalyticsRoute() string {
   381  	return fmt.Sprintf("/analytics")
   382  }
   383  
   384  func (c *Client4) GetTimezonesRoute() string {
   385  	return fmt.Sprintf(c.GetSystemRoute() + "/timezones")
   386  }
   387  
   388  func (c *Client4) GetChannelSchemeRoute(channelId string) string {
   389  	return fmt.Sprintf(c.GetChannelsRoute()+"/%v/scheme", channelId)
   390  }
   391  
   392  func (c *Client4) GetTeamSchemeRoute(teamId string) string {
   393  	return fmt.Sprintf(c.GetTeamsRoute()+"/%v/scheme", teamId)
   394  }
   395  
   396  func (c *Client4) GetTotalUsersStatsRoute() string {
   397  	return fmt.Sprintf(c.GetUsersRoute() + "/stats")
   398  }
   399  
   400  func (c *Client4) GetRedirectLocationRoute() string {
   401  	return fmt.Sprintf("/redirect_location")
   402  }
   403  
   404  func (c *Client4) GetUserTermsOfServiceRoute(userId string) string {
   405  	return c.GetUserRoute(userId) + "/terms_of_service"
   406  }
   407  
   408  func (c *Client4) GetTermsOfServiceRoute() string {
   409  	return "/terms_of_service"
   410  }
   411  
   412  func (c *Client4) GetGroupsRoute() string {
   413  	return "/groups"
   414  }
   415  
   416  func (c *Client4) GetGroupRoute(groupID string) string {
   417  	return fmt.Sprintf("%s/%s", c.GetGroupsRoute(), groupID)
   418  }
   419  
   420  func (c *Client4) GetGroupSyncableRoute(groupID, syncableID string, syncableType GroupSyncableType) string {
   421  	return fmt.Sprintf("%s/%ss/%s", c.GetGroupRoute(groupID), strings.ToLower(syncableType.String()), syncableID)
   422  }
   423  
   424  func (c *Client4) GetGroupSyncablesRoute(groupID string, syncableType GroupSyncableType) string {
   425  	return fmt.Sprintf("%s/%ss", c.GetGroupRoute(groupID), strings.ToLower(syncableType.String()))
   426  }
   427  
   428  func (c *Client4) DoApiGet(url string, etag string) (*http.Response, *AppError) {
   429  	return c.DoApiRequest(http.MethodGet, c.ApiUrl+url, "", etag)
   430  }
   431  
   432  func (c *Client4) DoApiPost(url string, data string) (*http.Response, *AppError) {
   433  	return c.DoApiRequest(http.MethodPost, c.ApiUrl+url, data, "")
   434  }
   435  
   436  func (c *Client4) doApiPostBytes(url string, data []byte) (*http.Response, *AppError) {
   437  	return c.doApiRequestBytes(http.MethodPost, c.ApiUrl+url, data, "")
   438  }
   439  
   440  func (c *Client4) DoApiPut(url string, data string) (*http.Response, *AppError) {
   441  	return c.DoApiRequest(http.MethodPut, c.ApiUrl+url, data, "")
   442  }
   443  
   444  func (c *Client4) DoApiDelete(url string) (*http.Response, *AppError) {
   445  	return c.DoApiRequest(http.MethodDelete, c.ApiUrl+url, "", "")
   446  }
   447  
   448  func (c *Client4) DoApiRequest(method, url, data, etag string) (*http.Response, *AppError) {
   449  	return c.doApiRequestReader(method, url, strings.NewReader(data), etag)
   450  }
   451  
   452  func (c *Client4) doApiRequestBytes(method, url string, data []byte, etag string) (*http.Response, *AppError) {
   453  	return c.doApiRequestReader(method, url, bytes.NewReader(data), etag)
   454  }
   455  
   456  func (c *Client4) doApiRequestReader(method, url string, data io.Reader, etag string) (*http.Response, *AppError) {
   457  	rq, err := http.NewRequest(method, url, data)
   458  	if err != nil {
   459  		return nil, NewAppError(url, "model.client.connecting.app_error", nil, err.Error(), http.StatusBadRequest)
   460  	}
   461  
   462  	if len(etag) > 0 {
   463  		rq.Header.Set(HEADER_ETAG_CLIENT, etag)
   464  	}
   465  
   466  	if len(c.AuthToken) > 0 {
   467  		rq.Header.Set(HEADER_AUTH, c.AuthType+" "+c.AuthToken)
   468  	}
   469  
   470  	if c.HttpHeader != nil && len(c.HttpHeader) > 0 {
   471  		for k, v := range c.HttpHeader {
   472  			rq.Header.Set(k, v)
   473  		}
   474  	}
   475  
   476  	rp, err := c.HttpClient.Do(rq)
   477  	if err != nil || rp == nil {
   478  		return nil, NewAppError(url, "model.client.connecting.app_error", nil, err.Error(), 0)
   479  	}
   480  
   481  	if rp.StatusCode == 304 {
   482  		return rp, nil
   483  	}
   484  
   485  	if rp.StatusCode >= 300 {
   486  		defer closeBody(rp)
   487  		return rp, AppErrorFromJson(rp.Body)
   488  	}
   489  
   490  	return rp, nil
   491  }
   492  
   493  func (c *Client4) DoUploadFile(url string, data []byte, contentType string) (*FileUploadResponse, *Response) {
   494  	return c.doUploadFile(url, bytes.NewReader(data), contentType, 0)
   495  }
   496  
   497  func (c *Client4) doUploadFile(url string, body io.Reader, contentType string, contentLength int64) (*FileUploadResponse, *Response) {
   498  	rq, err := http.NewRequest("POST", c.ApiUrl+url, body)
   499  	if err != nil {
   500  		return nil, &Response{Error: NewAppError(url, "model.client.connecting.app_error", nil, err.Error(), http.StatusBadRequest)}
   501  	}
   502  	if contentLength != 0 {
   503  		rq.ContentLength = contentLength
   504  	}
   505  	rq.Header.Set("Content-Type", contentType)
   506  
   507  	if len(c.AuthToken) > 0 {
   508  		rq.Header.Set(HEADER_AUTH, c.AuthType+" "+c.AuthToken)
   509  	}
   510  
   511  	rp, err := c.HttpClient.Do(rq)
   512  	if err != nil || rp == nil {
   513  		return nil, BuildErrorResponse(rp, NewAppError(url, "model.client.connecting.app_error", nil, err.Error(), 0))
   514  	}
   515  	defer closeBody(rp)
   516  
   517  	if rp.StatusCode >= 300 {
   518  		return nil, BuildErrorResponse(rp, AppErrorFromJson(rp.Body))
   519  	}
   520  
   521  	return FileUploadResponseFromJson(rp.Body), BuildResponse(rp)
   522  }
   523  
   524  func (c *Client4) DoEmojiUploadFile(url string, data []byte, contentType string) (*Emoji, *Response) {
   525  	rq, err := http.NewRequest("POST", c.ApiUrl+url, bytes.NewReader(data))
   526  	if err != nil {
   527  		return nil, &Response{Error: NewAppError(url, "model.client.connecting.app_error", nil, err.Error(), http.StatusBadRequest)}
   528  	}
   529  	rq.Header.Set("Content-Type", contentType)
   530  
   531  	if len(c.AuthToken) > 0 {
   532  		rq.Header.Set(HEADER_AUTH, c.AuthType+" "+c.AuthToken)
   533  	}
   534  
   535  	rp, err := c.HttpClient.Do(rq)
   536  	if err != nil || rp == nil {
   537  		return nil, BuildErrorResponse(rp, NewAppError(url, "model.client.connecting.app_error", nil, err.Error(), 0))
   538  	}
   539  	defer closeBody(rp)
   540  
   541  	if rp.StatusCode >= 300 {
   542  		return nil, BuildErrorResponse(rp, AppErrorFromJson(rp.Body))
   543  	}
   544  
   545  	return EmojiFromJson(rp.Body), BuildResponse(rp)
   546  }
   547  
   548  func (c *Client4) DoUploadImportTeam(url string, data []byte, contentType string) (map[string]string, *Response) {
   549  	rq, err := http.NewRequest("POST", c.ApiUrl+url, bytes.NewReader(data))
   550  	if err != nil {
   551  		return nil, &Response{Error: NewAppError(url, "model.client.connecting.app_error", nil, err.Error(), http.StatusBadRequest)}
   552  	}
   553  	rq.Header.Set("Content-Type", contentType)
   554  
   555  	if len(c.AuthToken) > 0 {
   556  		rq.Header.Set(HEADER_AUTH, c.AuthType+" "+c.AuthToken)
   557  	}
   558  
   559  	rp, err := c.HttpClient.Do(rq)
   560  	if err != nil || rp == nil {
   561  		return nil, BuildErrorResponse(rp, NewAppError(url, "model.client.connecting.app_error", nil, err.Error(), 0))
   562  	}
   563  	defer closeBody(rp)
   564  
   565  	if rp.StatusCode >= 300 {
   566  		return nil, BuildErrorResponse(rp, AppErrorFromJson(rp.Body))
   567  	}
   568  
   569  	return MapFromJson(rp.Body), BuildResponse(rp)
   570  }
   571  
   572  // CheckStatusOK is a convenience function for checking the standard OK response
   573  // from the web service.
   574  func CheckStatusOK(r *http.Response) bool {
   575  	m := MapFromJson(r.Body)
   576  	defer closeBody(r)
   577  
   578  	if m != nil && m[STATUS] == STATUS_OK {
   579  		return true
   580  	}
   581  
   582  	return false
   583  }
   584  
   585  // Authentication Section
   586  
   587  // LoginById authenticates a user by user id and password.
   588  func (c *Client4) LoginById(id string, password string) (*User, *Response) {
   589  	m := make(map[string]string)
   590  	m["id"] = id
   591  	m["password"] = password
   592  	return c.login(m)
   593  }
   594  
   595  // Login authenticates a user by login id, which can be username, email or some sort
   596  // of SSO identifier based on server configuration, and a password.
   597  func (c *Client4) Login(loginId string, password string) (*User, *Response) {
   598  	m := make(map[string]string)
   599  	m["login_id"] = loginId
   600  	m["password"] = password
   601  	return c.login(m)
   602  }
   603  
   604  // LoginByLdap authenticates a user by LDAP id and password.
   605  func (c *Client4) LoginByLdap(loginId string, password string) (*User, *Response) {
   606  	m := make(map[string]string)
   607  	m["login_id"] = loginId
   608  	m["password"] = password
   609  	m["ldap_only"] = "true"
   610  	return c.login(m)
   611  }
   612  
   613  // LoginWithDevice authenticates a user by login id (username, email or some sort
   614  // of SSO identifier based on configuration), password and attaches a device id to
   615  // the session.
   616  func (c *Client4) LoginWithDevice(loginId string, password string, deviceId string) (*User, *Response) {
   617  	m := make(map[string]string)
   618  	m["login_id"] = loginId
   619  	m["password"] = password
   620  	m["device_id"] = deviceId
   621  	return c.login(m)
   622  }
   623  
   624  func (c *Client4) login(m map[string]string) (*User, *Response) {
   625  	r, err := c.DoApiPost("/users/login", MapToJson(m))
   626  	if err != nil {
   627  		return nil, BuildErrorResponse(r, err)
   628  	}
   629  	defer closeBody(r)
   630  	c.AuthToken = r.Header.Get(HEADER_TOKEN)
   631  	c.AuthType = HEADER_BEARER
   632  	return UserFromJson(r.Body), BuildResponse(r)
   633  }
   634  
   635  // Logout terminates the current user's session.
   636  func (c *Client4) Logout() (bool, *Response) {
   637  	r, err := c.DoApiPost("/users/logout", "")
   638  	if err != nil {
   639  		return false, BuildErrorResponse(r, err)
   640  	}
   641  	defer closeBody(r)
   642  	c.AuthToken = ""
   643  	c.AuthType = HEADER_BEARER
   644  	return CheckStatusOK(r), BuildResponse(r)
   645  }
   646  
   647  // SwitchAccountType changes a user's login type from one type to another.
   648  func (c *Client4) SwitchAccountType(switchRequest *SwitchRequest) (string, *Response) {
   649  	r, err := c.DoApiPost(c.GetUsersRoute()+"/login/switch", switchRequest.ToJson())
   650  	if err != nil {
   651  		return "", BuildErrorResponse(r, err)
   652  	}
   653  	defer closeBody(r)
   654  	return MapFromJson(r.Body)["follow_link"], BuildResponse(r)
   655  }
   656  
   657  // User Section
   658  
   659  // CreateUser creates a user in the system based on the provided user struct.
   660  func (c *Client4) CreateUser(user *User) (*User, *Response) {
   661  	r, err := c.DoApiPost(c.GetUsersRoute(), user.ToJson())
   662  	if err != nil {
   663  		return nil, BuildErrorResponse(r, err)
   664  	}
   665  	defer closeBody(r)
   666  	return UserFromJson(r.Body), BuildResponse(r)
   667  }
   668  
   669  // CreateUserWithToken creates a user in the system based on the provided tokenId.
   670  func (c *Client4) CreateUserWithToken(user *User, tokenId string) (*User, *Response) {
   671  	if tokenId == "" {
   672  		err := NewAppError("MissingHashOrData", "api.user.create_user.missing_token.app_error", nil, "", http.StatusBadRequest)
   673  		return nil, &Response{StatusCode: err.StatusCode, Error: err}
   674  	}
   675  
   676  	query := fmt.Sprintf("?t=%v", tokenId)
   677  	r, err := c.DoApiPost(c.GetUsersRoute()+query, user.ToJson())
   678  	if err != nil {
   679  		return nil, BuildErrorResponse(r, err)
   680  	}
   681  	defer closeBody(r)
   682  
   683  	return UserFromJson(r.Body), BuildResponse(r)
   684  }
   685  
   686  // CreateUserWithInviteId creates a user in the system based on the provided invited id.
   687  func (c *Client4) CreateUserWithInviteId(user *User, inviteId string) (*User, *Response) {
   688  	if inviteId == "" {
   689  		err := NewAppError("MissingInviteId", "api.user.create_user.missing_invite_id.app_error", nil, "", http.StatusBadRequest)
   690  		return nil, &Response{StatusCode: err.StatusCode, Error: err}
   691  	}
   692  
   693  	query := fmt.Sprintf("?iid=%v", url.QueryEscape(inviteId))
   694  	r, err := c.DoApiPost(c.GetUsersRoute()+query, user.ToJson())
   695  	if err != nil {
   696  		return nil, BuildErrorResponse(r, err)
   697  	}
   698  	defer closeBody(r)
   699  
   700  	return UserFromJson(r.Body), BuildResponse(r)
   701  }
   702  
   703  // GetMe returns the logged in user.
   704  func (c *Client4) GetMe(etag string) (*User, *Response) {
   705  	r, err := c.DoApiGet(c.GetUserRoute(ME), etag)
   706  	if err != nil {
   707  		return nil, BuildErrorResponse(r, err)
   708  	}
   709  	defer closeBody(r)
   710  	return UserFromJson(r.Body), BuildResponse(r)
   711  }
   712  
   713  // GetUser returns a user based on the provided user id string.
   714  func (c *Client4) GetUser(userId, etag string) (*User, *Response) {
   715  	r, err := c.DoApiGet(c.GetUserRoute(userId), etag)
   716  	if err != nil {
   717  		return nil, BuildErrorResponse(r, err)
   718  	}
   719  	defer closeBody(r)
   720  	return UserFromJson(r.Body), BuildResponse(r)
   721  }
   722  
   723  // GetUserByUsername returns a user based on the provided user name string.
   724  func (c *Client4) GetUserByUsername(userName, etag string) (*User, *Response) {
   725  	r, err := c.DoApiGet(c.GetUserByUsernameRoute(userName), etag)
   726  	if err != nil {
   727  		return nil, BuildErrorResponse(r, err)
   728  	}
   729  	defer closeBody(r)
   730  	return UserFromJson(r.Body), BuildResponse(r)
   731  }
   732  
   733  // GetUserByEmail returns a user based on the provided user email string.
   734  func (c *Client4) GetUserByEmail(email, etag string) (*User, *Response) {
   735  	r, err := c.DoApiGet(c.GetUserByEmailRoute(email), etag)
   736  	if err != nil {
   737  		return nil, BuildErrorResponse(r, err)
   738  	}
   739  	defer closeBody(r)
   740  	return UserFromJson(r.Body), BuildResponse(r)
   741  }
   742  
   743  // AutocompleteUsersInTeam returns the users on a team based on search term.
   744  func (c *Client4) AutocompleteUsersInTeam(teamId string, username string, limit int, etag string) (*UserAutocomplete, *Response) {
   745  	query := fmt.Sprintf("?in_team=%v&name=%v&limit=%d", teamId, username, limit)
   746  	r, err := c.DoApiGet(c.GetUsersRoute()+"/autocomplete"+query, etag)
   747  	if err != nil {
   748  		return nil, BuildErrorResponse(r, err)
   749  	}
   750  	defer closeBody(r)
   751  	return UserAutocompleteFromJson(r.Body), BuildResponse(r)
   752  }
   753  
   754  // AutocompleteUsersInChannel returns the users in a channel based on search term.
   755  func (c *Client4) AutocompleteUsersInChannel(teamId string, channelId string, username string, limit int, etag string) (*UserAutocomplete, *Response) {
   756  	query := fmt.Sprintf("?in_team=%v&in_channel=%v&name=%v&limit=%d", teamId, channelId, username, limit)
   757  	r, err := c.DoApiGet(c.GetUsersRoute()+"/autocomplete"+query, etag)
   758  	if err != nil {
   759  		return nil, BuildErrorResponse(r, err)
   760  	}
   761  	defer closeBody(r)
   762  	return UserAutocompleteFromJson(r.Body), BuildResponse(r)
   763  }
   764  
   765  // AutocompleteUsers returns the users in the system based on search term.
   766  func (c *Client4) AutocompleteUsers(username string, limit int, etag string) (*UserAutocomplete, *Response) {
   767  	query := fmt.Sprintf("?name=%v&limit=%d", username, limit)
   768  	r, err := c.DoApiGet(c.GetUsersRoute()+"/autocomplete"+query, etag)
   769  	if err != nil {
   770  		return nil, BuildErrorResponse(r, err)
   771  	}
   772  	defer closeBody(r)
   773  	return UserAutocompleteFromJson(r.Body), BuildResponse(r)
   774  }
   775  
   776  // GetDefaultProfileImage gets the default user's profile image. Must be logged in.
   777  func (c *Client4) GetDefaultProfileImage(userId string) ([]byte, *Response) {
   778  	r, appErr := c.DoApiGet(c.GetUserRoute(userId)+"/image/default", "")
   779  	if appErr != nil {
   780  		return nil, BuildErrorResponse(r, appErr)
   781  	}
   782  	defer closeBody(r)
   783  
   784  	data, err := ioutil.ReadAll(r.Body)
   785  	if err != nil {
   786  		return nil, BuildErrorResponse(r, NewAppError("GetDefaultProfileImage", "model.client.read_file.app_error", nil, err.Error(), r.StatusCode))
   787  	}
   788  
   789  	return data, BuildResponse(r)
   790  }
   791  
   792  // GetProfileImage gets user's profile image. Must be logged in.
   793  func (c *Client4) GetProfileImage(userId, etag string) ([]byte, *Response) {
   794  	r, appErr := c.DoApiGet(c.GetUserRoute(userId)+"/image", etag)
   795  	if appErr != nil {
   796  		return nil, BuildErrorResponse(r, appErr)
   797  	}
   798  	defer closeBody(r)
   799  
   800  	data, err := ioutil.ReadAll(r.Body)
   801  	if err != nil {
   802  		return nil, BuildErrorResponse(r, NewAppError("GetProfileImage", "model.client.read_file.app_error", nil, err.Error(), r.StatusCode))
   803  	}
   804  	return data, BuildResponse(r)
   805  }
   806  
   807  // GetUsers returns a page of users on the system. Page counting starts at 0.
   808  func (c *Client4) GetUsers(page int, perPage int, etag string) ([]*User, *Response) {
   809  	query := fmt.Sprintf("?page=%v&per_page=%v", page, perPage)
   810  	r, err := c.DoApiGet(c.GetUsersRoute()+query, etag)
   811  	if err != nil {
   812  		return nil, BuildErrorResponse(r, err)
   813  	}
   814  	defer closeBody(r)
   815  	return UserListFromJson(r.Body), BuildResponse(r)
   816  }
   817  
   818  // GetUsersInTeam returns a page of users on a team. Page counting starts at 0.
   819  func (c *Client4) GetUsersInTeam(teamId string, page int, perPage int, etag string) ([]*User, *Response) {
   820  	query := fmt.Sprintf("?in_team=%v&page=%v&per_page=%v", teamId, page, perPage)
   821  	r, err := c.DoApiGet(c.GetUsersRoute()+query, etag)
   822  	if err != nil {
   823  		return nil, BuildErrorResponse(r, err)
   824  	}
   825  	defer closeBody(r)
   826  	return UserListFromJson(r.Body), BuildResponse(r)
   827  }
   828  
   829  // GetNewUsersInTeam returns a page of users on a team. Page counting starts at 0.
   830  func (c *Client4) GetNewUsersInTeam(teamId string, page int, perPage int, etag string) ([]*User, *Response) {
   831  	query := fmt.Sprintf("?sort=create_at&in_team=%v&page=%v&per_page=%v", teamId, page, perPage)
   832  	r, err := c.DoApiGet(c.GetUsersRoute()+query, etag)
   833  	if err != nil {
   834  		return nil, BuildErrorResponse(r, err)
   835  	}
   836  	defer closeBody(r)
   837  	return UserListFromJson(r.Body), BuildResponse(r)
   838  }
   839  
   840  // GetRecentlyActiveUsersInTeam returns a page of users on a team. Page counting starts at 0.
   841  func (c *Client4) GetRecentlyActiveUsersInTeam(teamId string, page int, perPage int, etag string) ([]*User, *Response) {
   842  	query := fmt.Sprintf("?sort=last_activity_at&in_team=%v&page=%v&per_page=%v", teamId, page, perPage)
   843  	r, err := c.DoApiGet(c.GetUsersRoute()+query, etag)
   844  	if err != nil {
   845  		return nil, BuildErrorResponse(r, err)
   846  	}
   847  	defer closeBody(r)
   848  	return UserListFromJson(r.Body), BuildResponse(r)
   849  }
   850  
   851  // GetUsersNotInTeam returns a page of users who are not in a team. Page counting starts at 0.
   852  func (c *Client4) GetUsersNotInTeam(teamId string, page int, perPage int, etag string) ([]*User, *Response) {
   853  	query := fmt.Sprintf("?not_in_team=%v&page=%v&per_page=%v", teamId, page, perPage)
   854  	r, err := c.DoApiGet(c.GetUsersRoute()+query, etag)
   855  	if err != nil {
   856  		return nil, BuildErrorResponse(r, err)
   857  	}
   858  	defer closeBody(r)
   859  	return UserListFromJson(r.Body), BuildResponse(r)
   860  }
   861  
   862  // GetUsersInChannel returns a page of users in a channel. Page counting starts at 0.
   863  func (c *Client4) GetUsersInChannel(channelId string, page int, perPage int, etag string) ([]*User, *Response) {
   864  	query := fmt.Sprintf("?in_channel=%v&page=%v&per_page=%v", channelId, page, perPage)
   865  	r, err := c.DoApiGet(c.GetUsersRoute()+query, etag)
   866  	if err != nil {
   867  		return nil, BuildErrorResponse(r, err)
   868  	}
   869  	defer closeBody(r)
   870  	return UserListFromJson(r.Body), BuildResponse(r)
   871  }
   872  
   873  // GetUsersInChannelByStatus returns a page of users in a channel. Page counting starts at 0. Sorted by Status
   874  func (c *Client4) GetUsersInChannelByStatus(channelId string, page int, perPage int, etag string) ([]*User, *Response) {
   875  	query := fmt.Sprintf("?in_channel=%v&page=%v&per_page=%v&sort=status", channelId, page, perPage)
   876  	r, err := c.DoApiGet(c.GetUsersRoute()+query, etag)
   877  	if err != nil {
   878  		return nil, BuildErrorResponse(r, err)
   879  	}
   880  	defer closeBody(r)
   881  	return UserListFromJson(r.Body), BuildResponse(r)
   882  }
   883  
   884  // GetUsersNotInChannel returns a page of users not in a channel. Page counting starts at 0.
   885  func (c *Client4) GetUsersNotInChannel(teamId, channelId string, page int, perPage int, etag string) ([]*User, *Response) {
   886  	query := fmt.Sprintf("?in_team=%v&not_in_channel=%v&page=%v&per_page=%v", teamId, channelId, page, perPage)
   887  	r, err := c.DoApiGet(c.GetUsersRoute()+query, etag)
   888  	if err != nil {
   889  		return nil, BuildErrorResponse(r, err)
   890  	}
   891  	defer closeBody(r)
   892  	return UserListFromJson(r.Body), BuildResponse(r)
   893  }
   894  
   895  // GetUsersWithoutTeam returns a page of users on the system that aren't on any teams. Page counting starts at 0.
   896  func (c *Client4) GetUsersWithoutTeam(page int, perPage int, etag string) ([]*User, *Response) {
   897  	query := fmt.Sprintf("?without_team=1&page=%v&per_page=%v", page, perPage)
   898  	r, err := c.DoApiGet(c.GetUsersRoute()+query, etag)
   899  	if err != nil {
   900  		return nil, BuildErrorResponse(r, err)
   901  	}
   902  	defer closeBody(r)
   903  	return UserListFromJson(r.Body), BuildResponse(r)
   904  }
   905  
   906  // GetUsersByIds returns a list of users based on the provided user ids.
   907  func (c *Client4) GetUsersByIds(userIds []string) ([]*User, *Response) {
   908  	r, err := c.DoApiPost(c.GetUsersRoute()+"/ids", ArrayToJson(userIds))
   909  	if err != nil {
   910  		return nil, BuildErrorResponse(r, err)
   911  	}
   912  	defer closeBody(r)
   913  	return UserListFromJson(r.Body), BuildResponse(r)
   914  }
   915  
   916  // GetUsersByUsernames returns a list of users based on the provided usernames.
   917  func (c *Client4) GetUsersByUsernames(usernames []string) ([]*User, *Response) {
   918  	r, err := c.DoApiPost(c.GetUsersRoute()+"/usernames", ArrayToJson(usernames))
   919  	if err != nil {
   920  		return nil, BuildErrorResponse(r, err)
   921  	}
   922  	defer closeBody(r)
   923  	return UserListFromJson(r.Body), BuildResponse(r)
   924  }
   925  
   926  // SearchUsers returns a list of users based on some search criteria.
   927  func (c *Client4) SearchUsers(search *UserSearch) ([]*User, *Response) {
   928  	r, err := c.doApiPostBytes(c.GetUsersRoute()+"/search", search.ToJson())
   929  	if err != nil {
   930  		return nil, BuildErrorResponse(r, err)
   931  	}
   932  	defer closeBody(r)
   933  	return UserListFromJson(r.Body), BuildResponse(r)
   934  }
   935  
   936  // UpdateUser updates a user in the system based on the provided user struct.
   937  func (c *Client4) UpdateUser(user *User) (*User, *Response) {
   938  	r, err := c.DoApiPut(c.GetUserRoute(user.Id), user.ToJson())
   939  	if err != nil {
   940  		return nil, BuildErrorResponse(r, err)
   941  	}
   942  	defer closeBody(r)
   943  	return UserFromJson(r.Body), BuildResponse(r)
   944  }
   945  
   946  // PatchUser partially updates a user in the system. Any missing fields are not updated.
   947  func (c *Client4) PatchUser(userId string, patch *UserPatch) (*User, *Response) {
   948  	r, err := c.DoApiPut(c.GetUserRoute(userId)+"/patch", patch.ToJson())
   949  	if err != nil {
   950  		return nil, BuildErrorResponse(r, err)
   951  	}
   952  	defer closeBody(r)
   953  	return UserFromJson(r.Body), BuildResponse(r)
   954  }
   955  
   956  // UpdateUserAuth updates a user AuthData (uthData, authService and password) in the system.
   957  func (c *Client4) UpdateUserAuth(userId string, userAuth *UserAuth) (*UserAuth, *Response) {
   958  	r, err := c.DoApiPut(c.GetUserRoute(userId)+"/auth", userAuth.ToJson())
   959  	if err != nil {
   960  		return nil, BuildErrorResponse(r, err)
   961  	}
   962  	defer closeBody(r)
   963  	return UserAuthFromJson(r.Body), BuildResponse(r)
   964  }
   965  
   966  // UpdateUserMfa activates multi-factor authentication for a user if activate
   967  // is true and a valid code is provided. If activate is false, then code is not
   968  // required and multi-factor authentication is disabled for the user.
   969  func (c *Client4) UpdateUserMfa(userId, code string, activate bool) (bool, *Response) {
   970  	requestBody := make(map[string]interface{})
   971  	requestBody["activate"] = activate
   972  	requestBody["code"] = code
   973  
   974  	r, err := c.DoApiPut(c.GetUserRoute(userId)+"/mfa", StringInterfaceToJson(requestBody))
   975  	if err != nil {
   976  		return false, BuildErrorResponse(r, err)
   977  	}
   978  	defer closeBody(r)
   979  	return CheckStatusOK(r), BuildResponse(r)
   980  }
   981  
   982  // CheckUserMfa checks whether a user has MFA active on their account or not based on the
   983  // provided login id.
   984  func (c *Client4) CheckUserMfa(loginId string) (bool, *Response) {
   985  	requestBody := make(map[string]interface{})
   986  	requestBody["login_id"] = loginId
   987  	r, err := c.DoApiPost(c.GetUsersRoute()+"/mfa", StringInterfaceToJson(requestBody))
   988  	if err != nil {
   989  		return false, BuildErrorResponse(r, err)
   990  	}
   991  	defer closeBody(r)
   992  
   993  	data := StringInterfaceFromJson(r.Body)
   994  	mfaRequired, ok := data["mfa_required"].(bool)
   995  	if !ok {
   996  		return false, BuildResponse(r)
   997  	}
   998  	return mfaRequired, BuildResponse(r)
   999  }
  1000  
  1001  // GenerateMfaSecret will generate a new MFA secret for a user and return it as a string and
  1002  // as a base64 encoded image QR code.
  1003  func (c *Client4) GenerateMfaSecret(userId string) (*MfaSecret, *Response) {
  1004  	r, err := c.DoApiPost(c.GetUserRoute(userId)+"/mfa/generate", "")
  1005  	if err != nil {
  1006  		return nil, BuildErrorResponse(r, err)
  1007  	}
  1008  	defer closeBody(r)
  1009  	return MfaSecretFromJson(r.Body), BuildResponse(r)
  1010  }
  1011  
  1012  // UpdateUserPassword updates a user's password. Must be logged in as the user or be a system administrator.
  1013  func (c *Client4) UpdateUserPassword(userId, currentPassword, newPassword string) (bool, *Response) {
  1014  	requestBody := map[string]string{"current_password": currentPassword, "new_password": newPassword}
  1015  	r, err := c.DoApiPut(c.GetUserRoute(userId)+"/password", MapToJson(requestBody))
  1016  	if err != nil {
  1017  		return false, BuildErrorResponse(r, err)
  1018  	}
  1019  	defer closeBody(r)
  1020  	return CheckStatusOK(r), BuildResponse(r)
  1021  }
  1022  
  1023  // UpdateUserRoles updates a user's roles in the system. A user can have "system_user" and "system_admin" roles.
  1024  func (c *Client4) UpdateUserRoles(userId, roles string) (bool, *Response) {
  1025  	requestBody := map[string]string{"roles": roles}
  1026  	r, err := c.DoApiPut(c.GetUserRoute(userId)+"/roles", MapToJson(requestBody))
  1027  	if err != nil {
  1028  		return false, BuildErrorResponse(r, err)
  1029  	}
  1030  	defer closeBody(r)
  1031  	return CheckStatusOK(r), BuildResponse(r)
  1032  }
  1033  
  1034  // UpdateUserActive updates status of a user whether active or not.
  1035  func (c *Client4) UpdateUserActive(userId string, active bool) (bool, *Response) {
  1036  	requestBody := make(map[string]interface{})
  1037  	requestBody["active"] = active
  1038  	r, err := c.DoApiPut(c.GetUserRoute(userId)+"/active", StringInterfaceToJson(requestBody))
  1039  	if err != nil {
  1040  		return false, BuildErrorResponse(r, err)
  1041  	}
  1042  	defer closeBody(r)
  1043  
  1044  	return CheckStatusOK(r), BuildResponse(r)
  1045  }
  1046  
  1047  // DeleteUser deactivates a user in the system based on the provided user id string.
  1048  func (c *Client4) DeleteUser(userId string) (bool, *Response) {
  1049  	r, err := c.DoApiDelete(c.GetUserRoute(userId))
  1050  	if err != nil {
  1051  		return false, BuildErrorResponse(r, err)
  1052  	}
  1053  	defer closeBody(r)
  1054  	return CheckStatusOK(r), BuildResponse(r)
  1055  }
  1056  
  1057  // SendPasswordResetEmail will send a link for password resetting to a user with the
  1058  // provided email.
  1059  func (c *Client4) SendPasswordResetEmail(email string) (bool, *Response) {
  1060  	requestBody := map[string]string{"email": email}
  1061  	r, err := c.DoApiPost(c.GetUsersRoute()+"/password/reset/send", MapToJson(requestBody))
  1062  	if err != nil {
  1063  		return false, BuildErrorResponse(r, err)
  1064  	}
  1065  	defer closeBody(r)
  1066  	return CheckStatusOK(r), BuildResponse(r)
  1067  }
  1068  
  1069  // ResetPassword uses a recovery code to update reset a user's password.
  1070  func (c *Client4) ResetPassword(token, newPassword string) (bool, *Response) {
  1071  	requestBody := map[string]string{"token": token, "new_password": newPassword}
  1072  	r, err := c.DoApiPost(c.GetUsersRoute()+"/password/reset", MapToJson(requestBody))
  1073  	if err != nil {
  1074  		return false, BuildErrorResponse(r, err)
  1075  	}
  1076  	defer closeBody(r)
  1077  	return CheckStatusOK(r), BuildResponse(r)
  1078  }
  1079  
  1080  // GetSessions returns a list of sessions based on the provided user id string.
  1081  func (c *Client4) GetSessions(userId, etag string) ([]*Session, *Response) {
  1082  	r, err := c.DoApiGet(c.GetUserRoute(userId)+"/sessions", etag)
  1083  	if err != nil {
  1084  		return nil, BuildErrorResponse(r, err)
  1085  	}
  1086  	defer closeBody(r)
  1087  	return SessionsFromJson(r.Body), BuildResponse(r)
  1088  }
  1089  
  1090  // RevokeSession revokes a user session based on the provided user id and session id strings.
  1091  func (c *Client4) RevokeSession(userId, sessionId string) (bool, *Response) {
  1092  	requestBody := map[string]string{"session_id": sessionId}
  1093  	r, err := c.DoApiPost(c.GetUserRoute(userId)+"/sessions/revoke", MapToJson(requestBody))
  1094  	if err != nil {
  1095  		return false, BuildErrorResponse(r, err)
  1096  	}
  1097  	defer closeBody(r)
  1098  	return CheckStatusOK(r), BuildResponse(r)
  1099  }
  1100  
  1101  // RevokeAllSessions revokes all sessions for the provided user id string.
  1102  func (c *Client4) RevokeAllSessions(userId string) (bool, *Response) {
  1103  	r, err := c.DoApiPost(c.GetUserRoute(userId)+"/sessions/revoke/all", "")
  1104  	if err != nil {
  1105  		return false, BuildErrorResponse(r, err)
  1106  	}
  1107  	defer closeBody(r)
  1108  	return CheckStatusOK(r), BuildResponse(r)
  1109  }
  1110  
  1111  // AttachDeviceId attaches a mobile device ID to the current session.
  1112  func (c *Client4) AttachDeviceId(deviceId string) (bool, *Response) {
  1113  	requestBody := map[string]string{"device_id": deviceId}
  1114  	r, err := c.DoApiPut(c.GetUsersRoute()+"/sessions/device", MapToJson(requestBody))
  1115  	if err != nil {
  1116  		return false, BuildErrorResponse(r, err)
  1117  	}
  1118  	defer closeBody(r)
  1119  	return CheckStatusOK(r), BuildResponse(r)
  1120  }
  1121  
  1122  // GetTeamsUnreadForUser will return an array with TeamUnread objects that contain the amount
  1123  // of unread messages and mentions the current user has for the teams it belongs to.
  1124  // An optional team ID can be set to exclude that team from the results. Must be authenticated.
  1125  func (c *Client4) GetTeamsUnreadForUser(userId, teamIdToExclude string) ([]*TeamUnread, *Response) {
  1126  	var optional string
  1127  	if teamIdToExclude != "" {
  1128  		optional += fmt.Sprintf("?exclude_team=%s", url.QueryEscape(teamIdToExclude))
  1129  	}
  1130  
  1131  	r, err := c.DoApiGet(c.GetUserRoute(userId)+"/teams/unread"+optional, "")
  1132  	if err != nil {
  1133  		return nil, BuildErrorResponse(r, err)
  1134  	}
  1135  	defer closeBody(r)
  1136  	return TeamsUnreadFromJson(r.Body), BuildResponse(r)
  1137  }
  1138  
  1139  // GetUserAudits returns a list of audit based on the provided user id string.
  1140  func (c *Client4) GetUserAudits(userId string, page int, perPage int, etag string) (Audits, *Response) {
  1141  	query := fmt.Sprintf("?page=%v&per_page=%v", page, perPage)
  1142  	r, err := c.DoApiGet(c.GetUserRoute(userId)+"/audits"+query, etag)
  1143  	if err != nil {
  1144  		return nil, BuildErrorResponse(r, err)
  1145  	}
  1146  	defer closeBody(r)
  1147  	return AuditsFromJson(r.Body), BuildResponse(r)
  1148  }
  1149  
  1150  // VerifyUserEmail will verify a user's email using the supplied token.
  1151  func (c *Client4) VerifyUserEmail(token string) (bool, *Response) {
  1152  	requestBody := map[string]string{"token": token}
  1153  	r, err := c.DoApiPost(c.GetUsersRoute()+"/email/verify", MapToJson(requestBody))
  1154  	if err != nil {
  1155  		return false, BuildErrorResponse(r, err)
  1156  	}
  1157  	defer closeBody(r)
  1158  	return CheckStatusOK(r), BuildResponse(r)
  1159  }
  1160  
  1161  // SendVerificationEmail will send an email to the user with the provided email address, if
  1162  // that user exists. The email will contain a link that can be used to verify the user's
  1163  // email address.
  1164  func (c *Client4) SendVerificationEmail(email string) (bool, *Response) {
  1165  	requestBody := map[string]string{"email": email}
  1166  	r, err := c.DoApiPost(c.GetUsersRoute()+"/email/verify/send", MapToJson(requestBody))
  1167  	if err != nil {
  1168  		return false, BuildErrorResponse(r, err)
  1169  	}
  1170  	defer closeBody(r)
  1171  	return CheckStatusOK(r), BuildResponse(r)
  1172  }
  1173  
  1174  // SetDefaultProfileImage resets the profile image to a default generated one.
  1175  func (c *Client4) SetDefaultProfileImage(userId string) (bool, *Response) {
  1176  	r, err := c.DoApiDelete(c.GetUserRoute(userId) + "/image")
  1177  	if err != nil {
  1178  		return false, BuildErrorResponse(r, err)
  1179  	}
  1180  	return CheckStatusOK(r), BuildResponse(r)
  1181  }
  1182  
  1183  // SetProfileImage sets profile image of the user.
  1184  func (c *Client4) SetProfileImage(userId string, data []byte) (bool, *Response) {
  1185  	body := &bytes.Buffer{}
  1186  	writer := multipart.NewWriter(body)
  1187  
  1188  	part, err := writer.CreateFormFile("image", "profile.png")
  1189  	if err != nil {
  1190  		return false, &Response{Error: NewAppError("SetProfileImage", "model.client.set_profile_user.no_file.app_error", nil, err.Error(), http.StatusBadRequest)}
  1191  	}
  1192  
  1193  	if _, err = io.Copy(part, bytes.NewBuffer(data)); err != nil {
  1194  		return false, &Response{Error: NewAppError("SetProfileImage", "model.client.set_profile_user.no_file.app_error", nil, err.Error(), http.StatusBadRequest)}
  1195  	}
  1196  
  1197  	if err = writer.Close(); err != nil {
  1198  		return false, &Response{Error: NewAppError("SetProfileImage", "model.client.set_profile_user.writer.app_error", nil, err.Error(), http.StatusBadRequest)}
  1199  	}
  1200  
  1201  	rq, err := http.NewRequest("POST", c.ApiUrl+c.GetUserRoute(userId)+"/image", bytes.NewReader(body.Bytes()))
  1202  	if err != nil {
  1203  		return false, &Response{Error: NewAppError("SetProfileImage", "model.client.connecting.app_error", nil, err.Error(), http.StatusBadRequest)}
  1204  	}
  1205  	rq.Header.Set("Content-Type", writer.FormDataContentType())
  1206  
  1207  	if len(c.AuthToken) > 0 {
  1208  		rq.Header.Set(HEADER_AUTH, c.AuthType+" "+c.AuthToken)
  1209  	}
  1210  
  1211  	rp, err := c.HttpClient.Do(rq)
  1212  	if err != nil || rp == nil {
  1213  		return false, &Response{StatusCode: http.StatusForbidden, Error: NewAppError(c.GetUserRoute(userId)+"/image", "model.client.connecting.app_error", nil, err.Error(), http.StatusForbidden)}
  1214  	}
  1215  	defer closeBody(rp)
  1216  
  1217  	if rp.StatusCode >= 300 {
  1218  		return false, BuildErrorResponse(rp, AppErrorFromJson(rp.Body))
  1219  	}
  1220  
  1221  	return CheckStatusOK(rp), BuildResponse(rp)
  1222  }
  1223  
  1224  // CreateUserAccessToken will generate a user access token that can be used in place
  1225  // of a session token to access the REST API. Must have the 'create_user_access_token'
  1226  // permission and if generating for another user, must have the 'edit_other_users'
  1227  // permission. A non-blank description is required.
  1228  func (c *Client4) CreateUserAccessToken(userId, description string) (*UserAccessToken, *Response) {
  1229  	requestBody := map[string]string{"description": description}
  1230  	r, err := c.DoApiPost(c.GetUserRoute(userId)+"/tokens", MapToJson(requestBody))
  1231  	if err != nil {
  1232  		return nil, BuildErrorResponse(r, err)
  1233  	}
  1234  	defer closeBody(r)
  1235  	return UserAccessTokenFromJson(r.Body), BuildResponse(r)
  1236  }
  1237  
  1238  // GetUserAccessTokens will get a page of access tokens' id, description, is_active
  1239  // and the user_id in the system. The actual token will not be returned. Must have
  1240  // the 'manage_system' permission.
  1241  func (c *Client4) GetUserAccessTokens(page int, perPage int) ([]*UserAccessToken, *Response) {
  1242  	query := fmt.Sprintf("?page=%v&per_page=%v", page, perPage)
  1243  	r, err := c.DoApiGet(c.GetUserAccessTokensRoute()+query, "")
  1244  	if err != nil {
  1245  		return nil, BuildErrorResponse(r, err)
  1246  	}
  1247  	defer closeBody(r)
  1248  	return UserAccessTokenListFromJson(r.Body), BuildResponse(r)
  1249  }
  1250  
  1251  // GetUserAccessToken will get a user access tokens' id, description, is_active
  1252  // and the user_id of the user it is for. The actual token will not be returned.
  1253  // Must have the 'read_user_access_token' permission and if getting for another
  1254  // user, must have the 'edit_other_users' permission.
  1255  func (c *Client4) GetUserAccessToken(tokenId string) (*UserAccessToken, *Response) {
  1256  	r, err := c.DoApiGet(c.GetUserAccessTokenRoute(tokenId), "")
  1257  	if err != nil {
  1258  		return nil, BuildErrorResponse(r, err)
  1259  	}
  1260  	defer closeBody(r)
  1261  	return UserAccessTokenFromJson(r.Body), BuildResponse(r)
  1262  }
  1263  
  1264  // GetUserAccessTokensForUser will get a paged list of user access tokens showing id,
  1265  // description and user_id for each. The actual tokens will not be returned. Must have
  1266  // the 'read_user_access_token' permission and if getting for another user, must have the
  1267  // 'edit_other_users' permission.
  1268  func (c *Client4) GetUserAccessTokensForUser(userId string, page, perPage int) ([]*UserAccessToken, *Response) {
  1269  	query := fmt.Sprintf("?page=%v&per_page=%v", page, perPage)
  1270  	r, err := c.DoApiGet(c.GetUserRoute(userId)+"/tokens"+query, "")
  1271  	if err != nil {
  1272  		return nil, BuildErrorResponse(r, err)
  1273  	}
  1274  	defer closeBody(r)
  1275  	return UserAccessTokenListFromJson(r.Body), BuildResponse(r)
  1276  }
  1277  
  1278  // RevokeUserAccessToken will revoke a user access token by id. Must have the
  1279  // 'revoke_user_access_token' permission and if revoking for another user, must have the
  1280  // 'edit_other_users' permission.
  1281  func (c *Client4) RevokeUserAccessToken(tokenId string) (bool, *Response) {
  1282  	requestBody := map[string]string{"token_id": tokenId}
  1283  	r, err := c.DoApiPost(c.GetUsersRoute()+"/tokens/revoke", MapToJson(requestBody))
  1284  	if err != nil {
  1285  		return false, BuildErrorResponse(r, err)
  1286  	}
  1287  	defer closeBody(r)
  1288  	return CheckStatusOK(r), BuildResponse(r)
  1289  }
  1290  
  1291  // SearchUserAccessTokens returns user access tokens matching the provided search term.
  1292  func (c *Client4) SearchUserAccessTokens(search *UserAccessTokenSearch) ([]*UserAccessToken, *Response) {
  1293  	r, err := c.DoApiPost(c.GetUsersRoute()+"/tokens/search", search.ToJson())
  1294  	if err != nil {
  1295  		return nil, BuildErrorResponse(r, err)
  1296  	}
  1297  	defer closeBody(r)
  1298  	return UserAccessTokenListFromJson(r.Body), BuildResponse(r)
  1299  }
  1300  
  1301  // DisableUserAccessToken will disable a user access token by id. Must have the
  1302  // 'revoke_user_access_token' permission and if disabling for another user, must have the
  1303  // 'edit_other_users' permission.
  1304  func (c *Client4) DisableUserAccessToken(tokenId string) (bool, *Response) {
  1305  	requestBody := map[string]string{"token_id": tokenId}
  1306  	r, err := c.DoApiPost(c.GetUsersRoute()+"/tokens/disable", MapToJson(requestBody))
  1307  	if err != nil {
  1308  		return false, BuildErrorResponse(r, err)
  1309  	}
  1310  	defer closeBody(r)
  1311  	return CheckStatusOK(r), BuildResponse(r)
  1312  }
  1313  
  1314  // EnableUserAccessToken will enable a user access token by id. Must have the
  1315  // 'create_user_access_token' permission and if enabling for another user, must have the
  1316  // 'edit_other_users' permission.
  1317  func (c *Client4) EnableUserAccessToken(tokenId string) (bool, *Response) {
  1318  	requestBody := map[string]string{"token_id": tokenId}
  1319  	r, err := c.DoApiPost(c.GetUsersRoute()+"/tokens/enable", MapToJson(requestBody))
  1320  	if err != nil {
  1321  		return false, BuildErrorResponse(r, err)
  1322  	}
  1323  	defer closeBody(r)
  1324  	return CheckStatusOK(r), BuildResponse(r)
  1325  }
  1326  
  1327  // Team Section
  1328  
  1329  // CreateTeam creates a team in the system based on the provided team struct.
  1330  func (c *Client4) CreateTeam(team *Team) (*Team, *Response) {
  1331  	r, err := c.DoApiPost(c.GetTeamsRoute(), team.ToJson())
  1332  	if err != nil {
  1333  		return nil, BuildErrorResponse(r, err)
  1334  	}
  1335  	defer closeBody(r)
  1336  	return TeamFromJson(r.Body), BuildResponse(r)
  1337  }
  1338  
  1339  // GetTeam returns a team based on the provided team id string.
  1340  func (c *Client4) GetTeam(teamId, etag string) (*Team, *Response) {
  1341  	r, err := c.DoApiGet(c.GetTeamRoute(teamId), etag)
  1342  	if err != nil {
  1343  		return nil, BuildErrorResponse(r, err)
  1344  	}
  1345  	defer closeBody(r)
  1346  	return TeamFromJson(r.Body), BuildResponse(r)
  1347  }
  1348  
  1349  // GetAllTeams returns all teams based on permissions.
  1350  func (c *Client4) GetAllTeams(etag string, page int, perPage int) ([]*Team, *Response) {
  1351  	query := fmt.Sprintf("?page=%v&per_page=%v", page, perPage)
  1352  	r, err := c.DoApiGet(c.GetTeamsRoute()+query, etag)
  1353  	if err != nil {
  1354  		return nil, BuildErrorResponse(r, err)
  1355  	}
  1356  	defer closeBody(r)
  1357  	return TeamListFromJson(r.Body), BuildResponse(r)
  1358  }
  1359  
  1360  // GetTeamByName returns a team based on the provided team name string.
  1361  func (c *Client4) GetTeamByName(name, etag string) (*Team, *Response) {
  1362  	r, err := c.DoApiGet(c.GetTeamByNameRoute(name), etag)
  1363  	if err != nil {
  1364  		return nil, BuildErrorResponse(r, err)
  1365  	}
  1366  	defer closeBody(r)
  1367  	return TeamFromJson(r.Body), BuildResponse(r)
  1368  }
  1369  
  1370  // SearchTeams returns teams matching the provided search term.
  1371  func (c *Client4) SearchTeams(search *TeamSearch) ([]*Team, *Response) {
  1372  	r, err := c.DoApiPost(c.GetTeamsRoute()+"/search", search.ToJson())
  1373  	if err != nil {
  1374  		return nil, BuildErrorResponse(r, err)
  1375  	}
  1376  	defer closeBody(r)
  1377  	return TeamListFromJson(r.Body), BuildResponse(r)
  1378  }
  1379  
  1380  // TeamExists returns true or false if the team exist or not.
  1381  func (c *Client4) TeamExists(name, etag string) (bool, *Response) {
  1382  	r, err := c.DoApiGet(c.GetTeamByNameRoute(name)+"/exists", etag)
  1383  	if err != nil {
  1384  		return false, BuildErrorResponse(r, err)
  1385  	}
  1386  	defer closeBody(r)
  1387  	return MapBoolFromJson(r.Body)["exists"], BuildResponse(r)
  1388  }
  1389  
  1390  // GetTeamsForUser returns a list of teams a user is on. Must be logged in as the user
  1391  // or be a system administrator.
  1392  func (c *Client4) GetTeamsForUser(userId, etag string) ([]*Team, *Response) {
  1393  	r, err := c.DoApiGet(c.GetUserRoute(userId)+"/teams", etag)
  1394  	if err != nil {
  1395  		return nil, BuildErrorResponse(r, err)
  1396  	}
  1397  	defer closeBody(r)
  1398  	return TeamListFromJson(r.Body), BuildResponse(r)
  1399  }
  1400  
  1401  // GetTeamMember returns a team member based on the provided team and user id strings.
  1402  func (c *Client4) GetTeamMember(teamId, userId, etag string) (*TeamMember, *Response) {
  1403  	r, err := c.DoApiGet(c.GetTeamMemberRoute(teamId, userId), etag)
  1404  	if err != nil {
  1405  		return nil, BuildErrorResponse(r, err)
  1406  	}
  1407  	defer closeBody(r)
  1408  	return TeamMemberFromJson(r.Body), BuildResponse(r)
  1409  }
  1410  
  1411  // UpdateTeamMemberRoles will update the roles on a team for a user.
  1412  func (c *Client4) UpdateTeamMemberRoles(teamId, userId, newRoles string) (bool, *Response) {
  1413  	requestBody := map[string]string{"roles": newRoles}
  1414  	r, err := c.DoApiPut(c.GetTeamMemberRoute(teamId, userId)+"/roles", MapToJson(requestBody))
  1415  	if err != nil {
  1416  		return false, BuildErrorResponse(r, err)
  1417  	}
  1418  	defer closeBody(r)
  1419  	return CheckStatusOK(r), BuildResponse(r)
  1420  }
  1421  
  1422  // UpdateTeamMemberSchemeRoles will update the scheme-derived roles on a team for a user.
  1423  func (c *Client4) UpdateTeamMemberSchemeRoles(teamId string, userId string, schemeRoles *SchemeRoles) (bool, *Response) {
  1424  	r, err := c.DoApiPut(c.GetTeamMemberRoute(teamId, userId)+"/schemeRoles", schemeRoles.ToJson())
  1425  	if err != nil {
  1426  		return false, BuildErrorResponse(r, err)
  1427  	}
  1428  	defer closeBody(r)
  1429  	return CheckStatusOK(r), BuildResponse(r)
  1430  }
  1431  
  1432  // UpdateTeam will update a team.
  1433  func (c *Client4) UpdateTeam(team *Team) (*Team, *Response) {
  1434  	r, err := c.DoApiPut(c.GetTeamRoute(team.Id), team.ToJson())
  1435  	if err != nil {
  1436  		return nil, BuildErrorResponse(r, err)
  1437  	}
  1438  	defer closeBody(r)
  1439  	return TeamFromJson(r.Body), BuildResponse(r)
  1440  }
  1441  
  1442  // PatchTeam partially updates a team. Any missing fields are not updated.
  1443  func (c *Client4) PatchTeam(teamId string, patch *TeamPatch) (*Team, *Response) {
  1444  	r, err := c.DoApiPut(c.GetTeamRoute(teamId)+"/patch", patch.ToJson())
  1445  	if err != nil {
  1446  		return nil, BuildErrorResponse(r, err)
  1447  	}
  1448  	defer closeBody(r)
  1449  	return TeamFromJson(r.Body), BuildResponse(r)
  1450  }
  1451  
  1452  // SoftDeleteTeam deletes the team softly (archive only, not permanent delete).
  1453  func (c *Client4) SoftDeleteTeam(teamId string) (bool, *Response) {
  1454  	r, err := c.DoApiDelete(c.GetTeamRoute(teamId))
  1455  	if err != nil {
  1456  		return false, BuildErrorResponse(r, err)
  1457  	}
  1458  	defer closeBody(r)
  1459  	return CheckStatusOK(r), BuildResponse(r)
  1460  }
  1461  
  1462  // PermanentDeleteTeam deletes the team, should only be used when needed for
  1463  // compliance and the like.
  1464  func (c *Client4) PermanentDeleteTeam(teamId string) (bool, *Response) {
  1465  	r, err := c.DoApiDelete(c.GetTeamRoute(teamId) + "?permanent=true")
  1466  	if err != nil {
  1467  		return false, BuildErrorResponse(r, err)
  1468  	}
  1469  	defer closeBody(r)
  1470  	return CheckStatusOK(r), BuildResponse(r)
  1471  }
  1472  
  1473  // GetTeamMembers returns team members based on the provided team id string.
  1474  func (c *Client4) GetTeamMembers(teamId string, page int, perPage int, etag string) ([]*TeamMember, *Response) {
  1475  	query := fmt.Sprintf("?page=%v&per_page=%v", page, perPage)
  1476  	r, err := c.DoApiGet(c.GetTeamMembersRoute(teamId)+query, etag)
  1477  	if err != nil {
  1478  		return nil, BuildErrorResponse(r, err)
  1479  	}
  1480  	defer closeBody(r)
  1481  	return TeamMembersFromJson(r.Body), BuildResponse(r)
  1482  }
  1483  
  1484  // GetTeamMembersForUser returns the team members for a user.
  1485  func (c *Client4) GetTeamMembersForUser(userId string, etag string) ([]*TeamMember, *Response) {
  1486  	r, err := c.DoApiGet(c.GetUserRoute(userId)+"/teams/members", etag)
  1487  	if err != nil {
  1488  		return nil, BuildErrorResponse(r, err)
  1489  	}
  1490  	defer closeBody(r)
  1491  	return TeamMembersFromJson(r.Body), BuildResponse(r)
  1492  }
  1493  
  1494  // GetTeamMembersByIds will return an array of team members based on the
  1495  // team id and a list of user ids provided. Must be authenticated.
  1496  func (c *Client4) GetTeamMembersByIds(teamId string, userIds []string) ([]*TeamMember, *Response) {
  1497  	r, err := c.DoApiPost(fmt.Sprintf("/teams/%v/members/ids", teamId), ArrayToJson(userIds))
  1498  	if err != nil {
  1499  		return nil, BuildErrorResponse(r, err)
  1500  	}
  1501  	defer closeBody(r)
  1502  	return TeamMembersFromJson(r.Body), BuildResponse(r)
  1503  }
  1504  
  1505  // AddTeamMember adds user to a team and return a team member.
  1506  func (c *Client4) AddTeamMember(teamId, userId string) (*TeamMember, *Response) {
  1507  	member := &TeamMember{TeamId: teamId, UserId: userId}
  1508  	r, err := c.DoApiPost(c.GetTeamMembersRoute(teamId), member.ToJson())
  1509  	if err != nil {
  1510  		return nil, BuildErrorResponse(r, err)
  1511  	}
  1512  	defer closeBody(r)
  1513  	return TeamMemberFromJson(r.Body), BuildResponse(r)
  1514  }
  1515  
  1516  // AddTeamMemberFromInvite adds a user to a team and return a team member using an invite id
  1517  // or an invite token/data pair.
  1518  func (c *Client4) AddTeamMemberFromInvite(token, inviteId string) (*TeamMember, *Response) {
  1519  	var query string
  1520  
  1521  	if inviteId != "" {
  1522  		query += fmt.Sprintf("?invite_id=%v", inviteId)
  1523  	}
  1524  
  1525  	if token != "" {
  1526  		query += fmt.Sprintf("?token=%v", token)
  1527  	}
  1528  
  1529  	r, err := c.DoApiPost(c.GetTeamsRoute()+"/members/invite"+query, "")
  1530  	if err != nil {
  1531  		return nil, BuildErrorResponse(r, err)
  1532  	}
  1533  	defer closeBody(r)
  1534  	return TeamMemberFromJson(r.Body), BuildResponse(r)
  1535  }
  1536  
  1537  // AddTeamMembers adds a number of users to a team and returns the team members.
  1538  func (c *Client4) AddTeamMembers(teamId string, userIds []string) ([]*TeamMember, *Response) {
  1539  	var members []*TeamMember
  1540  	for _, userId := range userIds {
  1541  		member := &TeamMember{TeamId: teamId, UserId: userId}
  1542  		members = append(members, member)
  1543  	}
  1544  
  1545  	r, err := c.DoApiPost(c.GetTeamMembersRoute(teamId)+"/batch", TeamMembersToJson(members))
  1546  	if err != nil {
  1547  		return nil, BuildErrorResponse(r, err)
  1548  	}
  1549  	defer closeBody(r)
  1550  	return TeamMembersFromJson(r.Body), BuildResponse(r)
  1551  }
  1552  
  1553  // RemoveTeamMember will remove a user from a team.
  1554  func (c *Client4) RemoveTeamMember(teamId, userId string) (bool, *Response) {
  1555  	r, err := c.DoApiDelete(c.GetTeamMemberRoute(teamId, userId))
  1556  	if err != nil {
  1557  		return false, BuildErrorResponse(r, err)
  1558  	}
  1559  	defer closeBody(r)
  1560  	return CheckStatusOK(r), BuildResponse(r)
  1561  }
  1562  
  1563  // GetTeamStats returns a team stats based on the team id string.
  1564  // Must be authenticated.
  1565  func (c *Client4) GetTeamStats(teamId, etag string) (*TeamStats, *Response) {
  1566  	r, err := c.DoApiGet(c.GetTeamStatsRoute(teamId), etag)
  1567  	if err != nil {
  1568  		return nil, BuildErrorResponse(r, err)
  1569  	}
  1570  	defer closeBody(r)
  1571  	return TeamStatsFromJson(r.Body), BuildResponse(r)
  1572  }
  1573  
  1574  // GetTotalUsersStats returns a total system user stats.
  1575  // Must be authenticated.
  1576  func (c *Client4) GetTotalUsersStats(etag string) (*UsersStats, *Response) {
  1577  	r, err := c.DoApiGet(c.GetTotalUsersStatsRoute(), etag)
  1578  	if err != nil {
  1579  		return nil, BuildErrorResponse(r, err)
  1580  	}
  1581  	defer closeBody(r)
  1582  	return UsersStatsFromJson(r.Body), BuildResponse(r)
  1583  }
  1584  
  1585  // GetTeamUnread will return a TeamUnread object that contains the amount of
  1586  // unread messages and mentions the user has for the specified team.
  1587  // Must be authenticated.
  1588  func (c *Client4) GetTeamUnread(teamId, userId string) (*TeamUnread, *Response) {
  1589  	r, err := c.DoApiGet(c.GetUserRoute(userId)+c.GetTeamRoute(teamId)+"/unread", "")
  1590  	if err != nil {
  1591  		return nil, BuildErrorResponse(r, err)
  1592  	}
  1593  	defer closeBody(r)
  1594  	return TeamUnreadFromJson(r.Body), BuildResponse(r)
  1595  }
  1596  
  1597  // ImportTeam will import an exported team from other app into a existing team.
  1598  func (c *Client4) ImportTeam(data []byte, filesize int, importFrom, filename, teamId string) (map[string]string, *Response) {
  1599  	body := &bytes.Buffer{}
  1600  	writer := multipart.NewWriter(body)
  1601  
  1602  	part, err := writer.CreateFormFile("file", filename)
  1603  	if err != nil {
  1604  		return nil, &Response{Error: NewAppError("UploadImportTeam", "model.client.upload_post_attachment.file.app_error", nil, err.Error(), http.StatusBadRequest)}
  1605  	}
  1606  
  1607  	if _, err = io.Copy(part, bytes.NewBuffer(data)); err != nil {
  1608  		return nil, &Response{Error: NewAppError("UploadImportTeam", "model.client.upload_post_attachment.file.app_error", nil, err.Error(), http.StatusBadRequest)}
  1609  	}
  1610  
  1611  	part, err = writer.CreateFormField("filesize")
  1612  	if err != nil {
  1613  		return nil, &Response{Error: NewAppError("UploadImportTeam", "model.client.upload_post_attachment.file_size.app_error", nil, err.Error(), http.StatusBadRequest)}
  1614  	}
  1615  
  1616  	if _, err = io.Copy(part, strings.NewReader(strconv.Itoa(filesize))); err != nil {
  1617  		return nil, &Response{Error: NewAppError("UploadImportTeam", "model.client.upload_post_attachment.file_size.app_error", nil, err.Error(), http.StatusBadRequest)}
  1618  	}
  1619  
  1620  	part, err = writer.CreateFormField("importFrom")
  1621  	if err != nil {
  1622  		return nil, &Response{Error: NewAppError("UploadImportTeam", "model.client.upload_post_attachment.import_from.app_error", nil, err.Error(), http.StatusBadRequest)}
  1623  	}
  1624  
  1625  	if _, err := io.Copy(part, strings.NewReader(importFrom)); err != nil {
  1626  		return nil, &Response{Error: NewAppError("UploadImportTeam", "model.client.upload_post_attachment.import_from.app_error", nil, err.Error(), http.StatusBadRequest)}
  1627  	}
  1628  
  1629  	if err := writer.Close(); err != nil {
  1630  		return nil, &Response{Error: NewAppError("UploadImportTeam", "model.client.upload_post_attachment.writer.app_error", nil, err.Error(), http.StatusBadRequest)}
  1631  	}
  1632  
  1633  	return c.DoUploadImportTeam(c.GetTeamImportRoute(teamId), body.Bytes(), writer.FormDataContentType())
  1634  }
  1635  
  1636  // InviteUsersToTeam invite users by email to the team.
  1637  func (c *Client4) InviteUsersToTeam(teamId string, userEmails []string) (bool, *Response) {
  1638  	r, err := c.DoApiPost(c.GetTeamRoute(teamId)+"/invite/email", ArrayToJson(userEmails))
  1639  	if err != nil {
  1640  		return false, BuildErrorResponse(r, err)
  1641  	}
  1642  	defer closeBody(r)
  1643  	return CheckStatusOK(r), BuildResponse(r)
  1644  }
  1645  
  1646  // GetTeamInviteInfo returns a team object from an invite id containing sanitized information.
  1647  func (c *Client4) GetTeamInviteInfo(inviteId string) (*Team, *Response) {
  1648  	r, err := c.DoApiGet(c.GetTeamsRoute()+"/invite/"+inviteId, "")
  1649  	if err != nil {
  1650  		return nil, BuildErrorResponse(r, err)
  1651  	}
  1652  	defer closeBody(r)
  1653  	return TeamFromJson(r.Body), BuildResponse(r)
  1654  }
  1655  
  1656  // SetTeamIcon sets team icon of the team.
  1657  func (c *Client4) SetTeamIcon(teamId string, data []byte) (bool, *Response) {
  1658  	body := &bytes.Buffer{}
  1659  	writer := multipart.NewWriter(body)
  1660  
  1661  	part, err := writer.CreateFormFile("image", "teamIcon.png")
  1662  	if err != nil {
  1663  		return false, &Response{Error: NewAppError("SetTeamIcon", "model.client.set_team_icon.no_file.app_error", nil, err.Error(), http.StatusBadRequest)}
  1664  	}
  1665  
  1666  	if _, err = io.Copy(part, bytes.NewBuffer(data)); err != nil {
  1667  		return false, &Response{Error: NewAppError("SetTeamIcon", "model.client.set_team_icon.no_file.app_error", nil, err.Error(), http.StatusBadRequest)}
  1668  	}
  1669  
  1670  	if err = writer.Close(); err != nil {
  1671  		return false, &Response{Error: NewAppError("SetTeamIcon", "model.client.set_team_icon.writer.app_error", nil, err.Error(), http.StatusBadRequest)}
  1672  	}
  1673  
  1674  	rq, err := http.NewRequest("POST", c.ApiUrl+c.GetTeamRoute(teamId)+"/image", bytes.NewReader(body.Bytes()))
  1675  	if err != nil {
  1676  		return false, &Response{Error: NewAppError("SetTeamIcon", "model.client.connecting.app_error", nil, err.Error(), http.StatusBadRequest)}
  1677  	}
  1678  	rq.Header.Set("Content-Type", writer.FormDataContentType())
  1679  
  1680  	if len(c.AuthToken) > 0 {
  1681  		rq.Header.Set(HEADER_AUTH, c.AuthType+" "+c.AuthToken)
  1682  	}
  1683  
  1684  	rp, err := c.HttpClient.Do(rq)
  1685  	if err != nil || rp == nil {
  1686  		// set to http.StatusForbidden(403)
  1687  		return false, &Response{StatusCode: http.StatusForbidden, Error: NewAppError(c.GetTeamRoute(teamId)+"/image", "model.client.connecting.app_error", nil, err.Error(), 403)}
  1688  	}
  1689  	defer closeBody(rp)
  1690  
  1691  	if rp.StatusCode >= 300 {
  1692  		return false, BuildErrorResponse(rp, AppErrorFromJson(rp.Body))
  1693  	}
  1694  
  1695  	return CheckStatusOK(rp), BuildResponse(rp)
  1696  }
  1697  
  1698  // GetTeamIcon gets the team icon of the team.
  1699  func (c *Client4) GetTeamIcon(teamId, etag string) ([]byte, *Response) {
  1700  	r, appErr := c.DoApiGet(c.GetTeamRoute(teamId)+"/image", etag)
  1701  	if appErr != nil {
  1702  		return nil, BuildErrorResponse(r, appErr)
  1703  	}
  1704  	defer closeBody(r)
  1705  
  1706  	data, err := ioutil.ReadAll(r.Body)
  1707  	if err != nil {
  1708  		return nil, BuildErrorResponse(r, NewAppError("GetTeamIcon", "model.client.get_team_icon.app_error", nil, err.Error(), r.StatusCode))
  1709  	}
  1710  	return data, BuildResponse(r)
  1711  }
  1712  
  1713  // RemoveTeamIcon updates LastTeamIconUpdate to 0 which indicates team icon is removed.
  1714  func (c *Client4) RemoveTeamIcon(teamId string) (bool, *Response) {
  1715  	r, err := c.DoApiDelete(c.GetTeamRoute(teamId) + "/image")
  1716  	if err != nil {
  1717  		return false, BuildErrorResponse(r, err)
  1718  	}
  1719  	defer closeBody(r)
  1720  	return CheckStatusOK(r), BuildResponse(r)
  1721  }
  1722  
  1723  // Channel Section
  1724  
  1725  // GetAllChannels get all the channels. Must be a system administrator.
  1726  func (c *Client4) GetAllChannels(page int, perPage int, etag string) (*ChannelListWithTeamData, *Response) {
  1727  	query := fmt.Sprintf("?page=%v&per_page=%v", page, perPage)
  1728  	r, err := c.DoApiGet(c.GetChannelsRoute()+query, etag)
  1729  	if err != nil {
  1730  		return nil, BuildErrorResponse(r, err)
  1731  	}
  1732  	defer closeBody(r)
  1733  	return ChannelListWithTeamDataFromJson(r.Body), BuildResponse(r)
  1734  }
  1735  
  1736  // CreateChannel creates a channel based on the provided channel struct.
  1737  func (c *Client4) CreateChannel(channel *Channel) (*Channel, *Response) {
  1738  	r, err := c.DoApiPost(c.GetChannelsRoute(), channel.ToJson())
  1739  	if err != nil {
  1740  		return nil, BuildErrorResponse(r, err)
  1741  	}
  1742  	defer closeBody(r)
  1743  	return ChannelFromJson(r.Body), BuildResponse(r)
  1744  }
  1745  
  1746  // UpdateChannel updates a channel based on the provided channel struct.
  1747  func (c *Client4) UpdateChannel(channel *Channel) (*Channel, *Response) {
  1748  	r, err := c.DoApiPut(c.GetChannelRoute(channel.Id), channel.ToJson())
  1749  	if err != nil {
  1750  		return nil, BuildErrorResponse(r, err)
  1751  	}
  1752  	defer closeBody(r)
  1753  	return ChannelFromJson(r.Body), BuildResponse(r)
  1754  }
  1755  
  1756  // PatchChannel partially updates a channel. Any missing fields are not updated.
  1757  func (c *Client4) PatchChannel(channelId string, patch *ChannelPatch) (*Channel, *Response) {
  1758  	r, err := c.DoApiPut(c.GetChannelRoute(channelId)+"/patch", patch.ToJson())
  1759  	if err != nil {
  1760  		return nil, BuildErrorResponse(r, err)
  1761  	}
  1762  	defer closeBody(r)
  1763  	return ChannelFromJson(r.Body), BuildResponse(r)
  1764  }
  1765  
  1766  // ConvertChannelToPrivate converts public to private channel.
  1767  func (c *Client4) ConvertChannelToPrivate(channelId string) (*Channel, *Response) {
  1768  	r, err := c.DoApiPost(c.GetChannelRoute(channelId)+"/convert", "")
  1769  	if err != nil {
  1770  		return nil, BuildErrorResponse(r, err)
  1771  	}
  1772  	defer closeBody(r)
  1773  	return ChannelFromJson(r.Body), BuildResponse(r)
  1774  }
  1775  
  1776  // RestoreChannel restores a previously deleted channel. Any missing fields are not updated.
  1777  func (c *Client4) RestoreChannel(channelId string) (*Channel, *Response) {
  1778  	r, err := c.DoApiPost(c.GetChannelRoute(channelId)+"/restore", "")
  1779  	if err != nil {
  1780  		return nil, BuildErrorResponse(r, err)
  1781  	}
  1782  	defer closeBody(r)
  1783  	return ChannelFromJson(r.Body), BuildResponse(r)
  1784  }
  1785  
  1786  // CreateDirectChannel creates a direct message channel based on the two user
  1787  // ids provided.
  1788  func (c *Client4) CreateDirectChannel(userId1, userId2 string) (*Channel, *Response) {
  1789  	requestBody := []string{userId1, userId2}
  1790  	r, err := c.DoApiPost(c.GetChannelsRoute()+"/direct", ArrayToJson(requestBody))
  1791  	if err != nil {
  1792  		return nil, BuildErrorResponse(r, err)
  1793  	}
  1794  	defer closeBody(r)
  1795  	return ChannelFromJson(r.Body), BuildResponse(r)
  1796  }
  1797  
  1798  // CreateGroupChannel creates a group message channel based on userIds provided.
  1799  func (c *Client4) CreateGroupChannel(userIds []string) (*Channel, *Response) {
  1800  	r, err := c.DoApiPost(c.GetChannelsRoute()+"/group", ArrayToJson(userIds))
  1801  	if err != nil {
  1802  		return nil, BuildErrorResponse(r, err)
  1803  	}
  1804  	defer closeBody(r)
  1805  	return ChannelFromJson(r.Body), BuildResponse(r)
  1806  }
  1807  
  1808  // GetChannel returns a channel based on the provided channel id string.
  1809  func (c *Client4) GetChannel(channelId, etag string) (*Channel, *Response) {
  1810  	r, err := c.DoApiGet(c.GetChannelRoute(channelId), etag)
  1811  	if err != nil {
  1812  		return nil, BuildErrorResponse(r, err)
  1813  	}
  1814  	defer closeBody(r)
  1815  	return ChannelFromJson(r.Body), BuildResponse(r)
  1816  }
  1817  
  1818  // GetChannelStats returns statistics for a channel.
  1819  func (c *Client4) GetChannelStats(channelId string, etag string) (*ChannelStats, *Response) {
  1820  	r, err := c.DoApiGet(c.GetChannelRoute(channelId)+"/stats", etag)
  1821  	if err != nil {
  1822  		return nil, BuildErrorResponse(r, err)
  1823  	}
  1824  	defer closeBody(r)
  1825  	return ChannelStatsFromJson(r.Body), BuildResponse(r)
  1826  }
  1827  
  1828  // GetChannelMembersTimezones gets a list of timezones for a channel.
  1829  func (c *Client4) GetChannelMembersTimezones(channelId string) ([]string, *Response) {
  1830  	r, err := c.DoApiGet(c.GetChannelRoute(channelId)+"/timezones", "")
  1831  	if err != nil {
  1832  		return nil, BuildErrorResponse(r, err)
  1833  	}
  1834  	defer closeBody(r)
  1835  	return ArrayFromJson(r.Body), BuildResponse(r)
  1836  }
  1837  
  1838  // GetPinnedPosts gets a list of pinned posts.
  1839  func (c *Client4) GetPinnedPosts(channelId string, etag string) (*PostList, *Response) {
  1840  	r, err := c.DoApiGet(c.GetChannelRoute(channelId)+"/pinned", etag)
  1841  	if err != nil {
  1842  		return nil, BuildErrorResponse(r, err)
  1843  	}
  1844  	defer closeBody(r)
  1845  	return PostListFromJson(r.Body), BuildResponse(r)
  1846  }
  1847  
  1848  // GetPublicChannelsForTeam returns a list of public channels based on the provided team id string.
  1849  func (c *Client4) GetPublicChannelsForTeam(teamId string, page int, perPage int, etag string) ([]*Channel, *Response) {
  1850  	query := fmt.Sprintf("?page=%v&per_page=%v", page, perPage)
  1851  	r, err := c.DoApiGet(c.GetChannelsForTeamRoute(teamId)+query, etag)
  1852  	if err != nil {
  1853  		return nil, BuildErrorResponse(r, err)
  1854  	}
  1855  	defer closeBody(r)
  1856  	return ChannelSliceFromJson(r.Body), BuildResponse(r)
  1857  }
  1858  
  1859  // GetDeletedChannelsForTeam returns a list of public channels based on the provided team id string.
  1860  func (c *Client4) GetDeletedChannelsForTeam(teamId string, page int, perPage int, etag string) ([]*Channel, *Response) {
  1861  	query := fmt.Sprintf("/deleted?page=%v&per_page=%v", page, perPage)
  1862  	r, err := c.DoApiGet(c.GetChannelsForTeamRoute(teamId)+query, etag)
  1863  	if err != nil {
  1864  		return nil, BuildErrorResponse(r, err)
  1865  	}
  1866  	defer closeBody(r)
  1867  	return ChannelSliceFromJson(r.Body), BuildResponse(r)
  1868  }
  1869  
  1870  // GetPublicChannelsByIdsForTeam returns a list of public channels based on provided team id string.
  1871  func (c *Client4) GetPublicChannelsByIdsForTeam(teamId string, channelIds []string) ([]*Channel, *Response) {
  1872  	r, err := c.DoApiPost(c.GetChannelsForTeamRoute(teamId)+"/ids", ArrayToJson(channelIds))
  1873  	if err != nil {
  1874  		return nil, BuildErrorResponse(r, err)
  1875  	}
  1876  	defer closeBody(r)
  1877  	return ChannelSliceFromJson(r.Body), BuildResponse(r)
  1878  }
  1879  
  1880  // GetChannelsForTeamForUser returns a list channels of on a team for a user.
  1881  func (c *Client4) GetChannelsForTeamForUser(teamId, userId, etag string) ([]*Channel, *Response) {
  1882  	r, err := c.DoApiGet(c.GetUserRoute(userId)+c.GetTeamRoute(teamId)+"/channels", etag)
  1883  	if err != nil {
  1884  		return nil, BuildErrorResponse(r, err)
  1885  	}
  1886  	defer closeBody(r)
  1887  	return ChannelSliceFromJson(r.Body), BuildResponse(r)
  1888  }
  1889  
  1890  // SearchChannels returns the channels on a team matching the provided search term.
  1891  func (c *Client4) SearchChannels(teamId string, search *ChannelSearch) ([]*Channel, *Response) {
  1892  	r, err := c.DoApiPost(c.GetChannelsForTeamRoute(teamId)+"/search", search.ToJson())
  1893  	if err != nil {
  1894  		return nil, BuildErrorResponse(r, err)
  1895  	}
  1896  	defer closeBody(r)
  1897  	return ChannelSliceFromJson(r.Body), BuildResponse(r)
  1898  }
  1899  
  1900  // SearchAllChannels search in all the channels. Must be a system administrator.
  1901  func (c *Client4) SearchAllChannels(search *ChannelSearch) (*ChannelListWithTeamData, *Response) {
  1902  	r, err := c.DoApiPost(c.GetChannelsRoute()+"/search", search.ToJson())
  1903  	if err != nil {
  1904  		return nil, BuildErrorResponse(r, err)
  1905  	}
  1906  	defer closeBody(r)
  1907  	return ChannelListWithTeamDataFromJson(r.Body), BuildResponse(r)
  1908  }
  1909  
  1910  // DeleteChannel deletes channel based on the provided channel id string.
  1911  func (c *Client4) DeleteChannel(channelId string) (bool, *Response) {
  1912  	r, err := c.DoApiDelete(c.GetChannelRoute(channelId))
  1913  	if err != nil {
  1914  		return false, BuildErrorResponse(r, err)
  1915  	}
  1916  	defer closeBody(r)
  1917  	return CheckStatusOK(r), BuildResponse(r)
  1918  }
  1919  
  1920  // GetChannelByName returns a channel based on the provided channel name and team id strings.
  1921  func (c *Client4) GetChannelByName(channelName, teamId string, etag string) (*Channel, *Response) {
  1922  	r, err := c.DoApiGet(c.GetChannelByNameRoute(channelName, teamId), etag)
  1923  	if err != nil {
  1924  		return nil, BuildErrorResponse(r, err)
  1925  	}
  1926  	defer closeBody(r)
  1927  	return ChannelFromJson(r.Body), BuildResponse(r)
  1928  }
  1929  
  1930  // GetChannelByNameIncludeDeleted returns a channel based on the provided channel name and team id strings. Other then GetChannelByName it will also return deleted channels.
  1931  func (c *Client4) GetChannelByNameIncludeDeleted(channelName, teamId string, etag string) (*Channel, *Response) {
  1932  	r, err := c.DoApiGet(c.GetChannelByNameRoute(channelName, teamId)+"?include_deleted=true", etag)
  1933  	if err != nil {
  1934  		return nil, BuildErrorResponse(r, err)
  1935  	}
  1936  	defer closeBody(r)
  1937  	return ChannelFromJson(r.Body), BuildResponse(r)
  1938  }
  1939  
  1940  // GetChannelByNameForTeamName returns a channel based on the provided channel name and team name strings.
  1941  func (c *Client4) GetChannelByNameForTeamName(channelName, teamName string, etag string) (*Channel, *Response) {
  1942  	r, err := c.DoApiGet(c.GetChannelByNameForTeamNameRoute(channelName, teamName), etag)
  1943  	if err != nil {
  1944  		return nil, BuildErrorResponse(r, err)
  1945  	}
  1946  	defer closeBody(r)
  1947  	return ChannelFromJson(r.Body), BuildResponse(r)
  1948  }
  1949  
  1950  // GetChannelByNameForTeamNameIncludeDeleted returns a channel based on the provided channel name and team name strings. Other then GetChannelByNameForTeamName it will also return deleted channels.
  1951  func (c *Client4) GetChannelByNameForTeamNameIncludeDeleted(channelName, teamName string, etag string) (*Channel, *Response) {
  1952  	r, err := c.DoApiGet(c.GetChannelByNameForTeamNameRoute(channelName, teamName)+"?include_deleted=true", etag)
  1953  	if err != nil {
  1954  		return nil, BuildErrorResponse(r, err)
  1955  	}
  1956  	defer closeBody(r)
  1957  	return ChannelFromJson(r.Body), BuildResponse(r)
  1958  }
  1959  
  1960  // GetChannelMembers gets a page of channel members.
  1961  func (c *Client4) GetChannelMembers(channelId string, page, perPage int, etag string) (*ChannelMembers, *Response) {
  1962  	query := fmt.Sprintf("?page=%v&per_page=%v", page, perPage)
  1963  	r, err := c.DoApiGet(c.GetChannelMembersRoute(channelId)+query, etag)
  1964  	if err != nil {
  1965  		return nil, BuildErrorResponse(r, err)
  1966  	}
  1967  	defer closeBody(r)
  1968  	return ChannelMembersFromJson(r.Body), BuildResponse(r)
  1969  }
  1970  
  1971  // GetChannelMembersByIds gets the channel members in a channel for a list of user ids.
  1972  func (c *Client4) GetChannelMembersByIds(channelId string, userIds []string) (*ChannelMembers, *Response) {
  1973  	r, err := c.DoApiPost(c.GetChannelMembersRoute(channelId)+"/ids", ArrayToJson(userIds))
  1974  	if err != nil {
  1975  		return nil, BuildErrorResponse(r, err)
  1976  	}
  1977  	defer closeBody(r)
  1978  	return ChannelMembersFromJson(r.Body), BuildResponse(r)
  1979  }
  1980  
  1981  // GetChannelMember gets a channel member.
  1982  func (c *Client4) GetChannelMember(channelId, userId, etag string) (*ChannelMember, *Response) {
  1983  	r, err := c.DoApiGet(c.GetChannelMemberRoute(channelId, userId), etag)
  1984  	if err != nil {
  1985  		return nil, BuildErrorResponse(r, err)
  1986  	}
  1987  	defer closeBody(r)
  1988  	return ChannelMemberFromJson(r.Body), BuildResponse(r)
  1989  }
  1990  
  1991  // GetChannelMembersForUser gets all the channel members for a user on a team.
  1992  func (c *Client4) GetChannelMembersForUser(userId, teamId, etag string) (*ChannelMembers, *Response) {
  1993  	r, err := c.DoApiGet(fmt.Sprintf(c.GetUserRoute(userId)+"/teams/%v/channels/members", teamId), etag)
  1994  	if err != nil {
  1995  		return nil, BuildErrorResponse(r, err)
  1996  	}
  1997  	defer closeBody(r)
  1998  	return ChannelMembersFromJson(r.Body), BuildResponse(r)
  1999  }
  2000  
  2001  // ViewChannel performs a view action for a user. Synonymous with switching channels or marking channels as read by a user.
  2002  func (c *Client4) ViewChannel(userId string, view *ChannelView) (*ChannelViewResponse, *Response) {
  2003  	url := fmt.Sprintf(c.GetChannelsRoute()+"/members/%v/view", userId)
  2004  	r, err := c.DoApiPost(url, view.ToJson())
  2005  	if err != nil {
  2006  		return nil, BuildErrorResponse(r, err)
  2007  	}
  2008  	defer closeBody(r)
  2009  	return ChannelViewResponseFromJson(r.Body), BuildResponse(r)
  2010  }
  2011  
  2012  // GetChannelUnread will return a ChannelUnread object that contains the number of
  2013  // unread messages and mentions for a user.
  2014  func (c *Client4) GetChannelUnread(channelId, userId string) (*ChannelUnread, *Response) {
  2015  	r, err := c.DoApiGet(c.GetUserRoute(userId)+c.GetChannelRoute(channelId)+"/unread", "")
  2016  	if err != nil {
  2017  		return nil, BuildErrorResponse(r, err)
  2018  	}
  2019  	defer closeBody(r)
  2020  	return ChannelUnreadFromJson(r.Body), BuildResponse(r)
  2021  }
  2022  
  2023  // UpdateChannelRoles will update the roles on a channel for a user.
  2024  func (c *Client4) UpdateChannelRoles(channelId, userId, roles string) (bool, *Response) {
  2025  	requestBody := map[string]string{"roles": roles}
  2026  	r, err := c.DoApiPut(c.GetChannelMemberRoute(channelId, userId)+"/roles", MapToJson(requestBody))
  2027  	if err != nil {
  2028  		return false, BuildErrorResponse(r, err)
  2029  	}
  2030  	defer closeBody(r)
  2031  	return CheckStatusOK(r), BuildResponse(r)
  2032  }
  2033  
  2034  // UpdateChannelMemberSchemeRoles will update the scheme-derived roles on a channel for a user.
  2035  func (c *Client4) UpdateChannelMemberSchemeRoles(channelId string, userId string, schemeRoles *SchemeRoles) (bool, *Response) {
  2036  	r, err := c.DoApiPut(c.GetChannelMemberRoute(channelId, userId)+"/schemeRoles", schemeRoles.ToJson())
  2037  	if err != nil {
  2038  		return false, BuildErrorResponse(r, err)
  2039  	}
  2040  	defer closeBody(r)
  2041  	return CheckStatusOK(r), BuildResponse(r)
  2042  }
  2043  
  2044  // UpdateChannelNotifyProps will update the notification properties on a channel for a user.
  2045  func (c *Client4) UpdateChannelNotifyProps(channelId, userId string, props map[string]string) (bool, *Response) {
  2046  	r, err := c.DoApiPut(c.GetChannelMemberRoute(channelId, userId)+"/notify_props", MapToJson(props))
  2047  	if err != nil {
  2048  		return false, BuildErrorResponse(r, err)
  2049  	}
  2050  	defer closeBody(r)
  2051  	return CheckStatusOK(r), BuildResponse(r)
  2052  }
  2053  
  2054  // AddChannelMember adds user to channel and return a channel member.
  2055  func (c *Client4) AddChannelMember(channelId, userId string) (*ChannelMember, *Response) {
  2056  	requestBody := map[string]string{"user_id": userId}
  2057  	r, err := c.DoApiPost(c.GetChannelMembersRoute(channelId)+"", MapToJson(requestBody))
  2058  	if err != nil {
  2059  		return nil, BuildErrorResponse(r, err)
  2060  	}
  2061  	defer closeBody(r)
  2062  	return ChannelMemberFromJson(r.Body), BuildResponse(r)
  2063  }
  2064  
  2065  // AddChannelMemberWithRootId adds user to channel and return a channel member. Post add to channel message has the postRootId.
  2066  func (c *Client4) AddChannelMemberWithRootId(channelId, userId, postRootId string) (*ChannelMember, *Response) {
  2067  	requestBody := map[string]string{"user_id": userId, "post_root_id": postRootId}
  2068  	r, err := c.DoApiPost(c.GetChannelMembersRoute(channelId)+"", MapToJson(requestBody))
  2069  	if err != nil {
  2070  		return nil, BuildErrorResponse(r, err)
  2071  	}
  2072  	defer closeBody(r)
  2073  	return ChannelMemberFromJson(r.Body), BuildResponse(r)
  2074  }
  2075  
  2076  // RemoveUserFromChannel will delete the channel member object for a user, effectively removing the user from a channel.
  2077  func (c *Client4) RemoveUserFromChannel(channelId, userId string) (bool, *Response) {
  2078  	r, err := c.DoApiDelete(c.GetChannelMemberRoute(channelId, userId))
  2079  	if err != nil {
  2080  		return false, BuildErrorResponse(r, err)
  2081  	}
  2082  	defer closeBody(r)
  2083  	return CheckStatusOK(r), BuildResponse(r)
  2084  }
  2085  
  2086  // AutocompleteChannelsForTeam will return an ordered list of channels autocomplete suggestions.
  2087  func (c *Client4) AutocompleteChannelsForTeam(teamId, name string) (*ChannelList, *Response) {
  2088  	query := fmt.Sprintf("?name=%v", name)
  2089  	r, err := c.DoApiGet(c.GetChannelsForTeamRoute(teamId)+"/autocomplete"+query, "")
  2090  	if err != nil {
  2091  		return nil, BuildErrorResponse(r, err)
  2092  	}
  2093  	defer closeBody(r)
  2094  	return ChannelListFromJson(r.Body), BuildResponse(r)
  2095  }
  2096  
  2097  // AutocompleteChannelsForTeamForSearch will return an ordered list of your channels autocomplete suggestions.
  2098  func (c *Client4) AutocompleteChannelsForTeamForSearch(teamId, name string) (*ChannelList, *Response) {
  2099  	query := fmt.Sprintf("?name=%v", name)
  2100  	r, err := c.DoApiGet(c.GetChannelsForTeamRoute(teamId)+"/search_autocomplete"+query, "")
  2101  	if err != nil {
  2102  		return nil, BuildErrorResponse(r, err)
  2103  	}
  2104  	defer closeBody(r)
  2105  	return ChannelListFromJson(r.Body), BuildResponse(r)
  2106  }
  2107  
  2108  // Post Section
  2109  
  2110  // CreatePost creates a post based on the provided post struct.
  2111  func (c *Client4) CreatePost(post *Post) (*Post, *Response) {
  2112  	r, err := c.DoApiPost(c.GetPostsRoute(), post.ToUnsanitizedJson())
  2113  	if err != nil {
  2114  		return nil, BuildErrorResponse(r, err)
  2115  	}
  2116  	defer closeBody(r)
  2117  	return PostFromJson(r.Body), BuildResponse(r)
  2118  }
  2119  
  2120  // CreatePostEphemeral creates a ephemeral post based on the provided post struct which is send to the given user id.
  2121  func (c *Client4) CreatePostEphemeral(post *PostEphemeral) (*Post, *Response) {
  2122  	r, err := c.DoApiPost(c.GetPostsEphemeralRoute(), post.ToUnsanitizedJson())
  2123  	if err != nil {
  2124  		return nil, BuildErrorResponse(r, err)
  2125  	}
  2126  	defer closeBody(r)
  2127  	return PostFromJson(r.Body), BuildResponse(r)
  2128  }
  2129  
  2130  // UpdatePost updates a post based on the provided post struct.
  2131  func (c *Client4) UpdatePost(postId string, post *Post) (*Post, *Response) {
  2132  	r, err := c.DoApiPut(c.GetPostRoute(postId), post.ToUnsanitizedJson())
  2133  	if err != nil {
  2134  		return nil, BuildErrorResponse(r, err)
  2135  	}
  2136  	defer closeBody(r)
  2137  	return PostFromJson(r.Body), BuildResponse(r)
  2138  }
  2139  
  2140  // PatchPost partially updates a post. Any missing fields are not updated.
  2141  func (c *Client4) PatchPost(postId string, patch *PostPatch) (*Post, *Response) {
  2142  	r, err := c.DoApiPut(c.GetPostRoute(postId)+"/patch", patch.ToJson())
  2143  	if err != nil {
  2144  		return nil, BuildErrorResponse(r, err)
  2145  	}
  2146  	defer closeBody(r)
  2147  	return PostFromJson(r.Body), BuildResponse(r)
  2148  }
  2149  
  2150  // PinPost pin a post based on provided post id string.
  2151  func (c *Client4) PinPost(postId string) (bool, *Response) {
  2152  	r, err := c.DoApiPost(c.GetPostRoute(postId)+"/pin", "")
  2153  	if err != nil {
  2154  		return false, BuildErrorResponse(r, err)
  2155  	}
  2156  	defer closeBody(r)
  2157  	return CheckStatusOK(r), BuildResponse(r)
  2158  }
  2159  
  2160  // UnpinPost unpin a post based on provided post id string.
  2161  func (c *Client4) UnpinPost(postId string) (bool, *Response) {
  2162  	r, err := c.DoApiPost(c.GetPostRoute(postId)+"/unpin", "")
  2163  	if err != nil {
  2164  		return false, BuildErrorResponse(r, err)
  2165  	}
  2166  	defer closeBody(r)
  2167  	return CheckStatusOK(r), BuildResponse(r)
  2168  }
  2169  
  2170  // GetPost gets a single post.
  2171  func (c *Client4) GetPost(postId string, etag string) (*Post, *Response) {
  2172  	r, err := c.DoApiGet(c.GetPostRoute(postId), etag)
  2173  	if err != nil {
  2174  		return nil, BuildErrorResponse(r, err)
  2175  	}
  2176  	defer closeBody(r)
  2177  	return PostFromJson(r.Body), BuildResponse(r)
  2178  }
  2179  
  2180  // DeletePost deletes a post from the provided post id string.
  2181  func (c *Client4) DeletePost(postId string) (bool, *Response) {
  2182  	r, err := c.DoApiDelete(c.GetPostRoute(postId))
  2183  	if err != nil {
  2184  		return false, BuildErrorResponse(r, err)
  2185  	}
  2186  	defer closeBody(r)
  2187  	return CheckStatusOK(r), BuildResponse(r)
  2188  }
  2189  
  2190  // GetPostThread gets a post with all the other posts in the same thread.
  2191  func (c *Client4) GetPostThread(postId string, etag string) (*PostList, *Response) {
  2192  	r, err := c.DoApiGet(c.GetPostRoute(postId)+"/thread", etag)
  2193  	if err != nil {
  2194  		return nil, BuildErrorResponse(r, err)
  2195  	}
  2196  	defer closeBody(r)
  2197  	return PostListFromJson(r.Body), BuildResponse(r)
  2198  }
  2199  
  2200  // GetPostsForChannel gets a page of posts with an array for ordering for a channel.
  2201  func (c *Client4) GetPostsForChannel(channelId string, page, perPage int, etag string) (*PostList, *Response) {
  2202  	query := fmt.Sprintf("?page=%v&per_page=%v", page, perPage)
  2203  	r, err := c.DoApiGet(c.GetChannelRoute(channelId)+"/posts"+query, etag)
  2204  	if err != nil {
  2205  		return nil, BuildErrorResponse(r, err)
  2206  	}
  2207  	defer closeBody(r)
  2208  	return PostListFromJson(r.Body), BuildResponse(r)
  2209  }
  2210  
  2211  // GetFlaggedPostsForUser returns flagged posts of a user based on user id string.
  2212  func (c *Client4) GetFlaggedPostsForUser(userId string, page int, perPage int) (*PostList, *Response) {
  2213  	query := fmt.Sprintf("?page=%v&per_page=%v", page, perPage)
  2214  	r, err := c.DoApiGet(c.GetUserRoute(userId)+"/posts/flagged"+query, "")
  2215  	if err != nil {
  2216  		return nil, BuildErrorResponse(r, err)
  2217  	}
  2218  	defer closeBody(r)
  2219  	return PostListFromJson(r.Body), BuildResponse(r)
  2220  }
  2221  
  2222  // GetFlaggedPostsForUserInTeam returns flagged posts in team of a user based on user id string.
  2223  func (c *Client4) GetFlaggedPostsForUserInTeam(userId string, teamId string, page int, perPage int) (*PostList, *Response) {
  2224  	if len(teamId) == 0 || len(teamId) != 26 {
  2225  		return nil, &Response{StatusCode: http.StatusBadRequest, Error: NewAppError("GetFlaggedPostsForUserInTeam", "model.client.get_flagged_posts_in_team.missing_parameter.app_error", nil, "", http.StatusBadRequest)}
  2226  	}
  2227  
  2228  	query := fmt.Sprintf("?team_id=%v&page=%v&per_page=%v", teamId, page, perPage)
  2229  	r, err := c.DoApiGet(c.GetUserRoute(userId)+"/posts/flagged"+query, "")
  2230  	if err != nil {
  2231  		return nil, BuildErrorResponse(r, err)
  2232  	}
  2233  	defer closeBody(r)
  2234  	return PostListFromJson(r.Body), BuildResponse(r)
  2235  }
  2236  
  2237  // GetFlaggedPostsForUserInChannel returns flagged posts in channel of a user based on user id string.
  2238  func (c *Client4) GetFlaggedPostsForUserInChannel(userId string, channelId string, page int, perPage int) (*PostList, *Response) {
  2239  	if len(channelId) == 0 || len(channelId) != 26 {
  2240  		return nil, &Response{StatusCode: http.StatusBadRequest, Error: NewAppError("GetFlaggedPostsForUserInChannel", "model.client.get_flagged_posts_in_channel.missing_parameter.app_error", nil, "", http.StatusBadRequest)}
  2241  	}
  2242  
  2243  	query := fmt.Sprintf("?channel_id=%v&page=%v&per_page=%v", channelId, page, perPage)
  2244  	r, err := c.DoApiGet(c.GetUserRoute(userId)+"/posts/flagged"+query, "")
  2245  	if err != nil {
  2246  		return nil, BuildErrorResponse(r, err)
  2247  	}
  2248  	defer closeBody(r)
  2249  	return PostListFromJson(r.Body), BuildResponse(r)
  2250  }
  2251  
  2252  // GetPostsSince gets posts created after a specified time as Unix time in milliseconds.
  2253  func (c *Client4) GetPostsSince(channelId string, time int64) (*PostList, *Response) {
  2254  	query := fmt.Sprintf("?since=%v", time)
  2255  	r, err := c.DoApiGet(c.GetChannelRoute(channelId)+"/posts"+query, "")
  2256  	if err != nil {
  2257  		return nil, BuildErrorResponse(r, err)
  2258  	}
  2259  	defer closeBody(r)
  2260  	return PostListFromJson(r.Body), BuildResponse(r)
  2261  }
  2262  
  2263  // GetPostsAfter gets a page of posts that were posted after the post provided.
  2264  func (c *Client4) GetPostsAfter(channelId, postId string, page, perPage int, etag string) (*PostList, *Response) {
  2265  	query := fmt.Sprintf("?page=%v&per_page=%v&after=%v", page, perPage, postId)
  2266  	r, err := c.DoApiGet(c.GetChannelRoute(channelId)+"/posts"+query, etag)
  2267  	if err != nil {
  2268  		return nil, BuildErrorResponse(r, err)
  2269  	}
  2270  	defer closeBody(r)
  2271  	return PostListFromJson(r.Body), BuildResponse(r)
  2272  }
  2273  
  2274  // GetPostsBefore gets a page of posts that were posted before the post provided.
  2275  func (c *Client4) GetPostsBefore(channelId, postId string, page, perPage int, etag string) (*PostList, *Response) {
  2276  	query := fmt.Sprintf("?page=%v&per_page=%v&before=%v", page, perPage, postId)
  2277  	r, err := c.DoApiGet(c.GetChannelRoute(channelId)+"/posts"+query, etag)
  2278  	if err != nil {
  2279  		return nil, BuildErrorResponse(r, err)
  2280  	}
  2281  	defer closeBody(r)
  2282  	return PostListFromJson(r.Body), BuildResponse(r)
  2283  }
  2284  
  2285  // SearchPosts returns any posts with matching terms string.
  2286  func (c *Client4) SearchPosts(teamId string, terms string, isOrSearch bool) (*PostList, *Response) {
  2287  	params := SearchParameter{
  2288  		Terms:      &terms,
  2289  		IsOrSearch: &isOrSearch,
  2290  	}
  2291  	return c.SearchPostsWithParams(teamId, &params)
  2292  }
  2293  
  2294  // SearchPostsWithParams returns any posts with matching terms string.
  2295  func (c *Client4) SearchPostsWithParams(teamId string, params *SearchParameter) (*PostList, *Response) {
  2296  	r, err := c.DoApiPost(c.GetTeamRoute(teamId)+"/posts/search", params.SearchParameterToJson())
  2297  	if err != nil {
  2298  		return nil, BuildErrorResponse(r, err)
  2299  	}
  2300  	defer closeBody(r)
  2301  	return PostListFromJson(r.Body), BuildResponse(r)
  2302  }
  2303  
  2304  // SearchPostsWithMatches returns any posts with matching terms string, including.
  2305  func (c *Client4) SearchPostsWithMatches(teamId string, terms string, isOrSearch bool) (*PostSearchResults, *Response) {
  2306  	requestBody := map[string]interface{}{"terms": terms, "is_or_search": isOrSearch}
  2307  	r, err := c.DoApiPost(c.GetTeamRoute(teamId)+"/posts/search", StringInterfaceToJson(requestBody))
  2308  	if err != nil {
  2309  		return nil, BuildErrorResponse(r, err)
  2310  	}
  2311  	defer closeBody(r)
  2312  	return PostSearchResultsFromJson(r.Body), BuildResponse(r)
  2313  }
  2314  
  2315  // DoPostAction performs a post action.
  2316  func (c *Client4) DoPostAction(postId, actionId string) (bool, *Response) {
  2317  	r, err := c.DoApiPost(c.GetPostRoute(postId)+"/actions/"+actionId, "")
  2318  	if err != nil {
  2319  		return false, BuildErrorResponse(r, err)
  2320  	}
  2321  	defer closeBody(r)
  2322  	return CheckStatusOK(r), BuildResponse(r)
  2323  }
  2324  
  2325  // OpenInteractiveDialog sends a WebSocket event to a user's clients to
  2326  // open interactive dialogs, based on the provided trigger ID and other
  2327  // provided data. Used with interactive message buttons, menus and
  2328  // slash commands.
  2329  func (c *Client4) OpenInteractiveDialog(request OpenDialogRequest) (bool, *Response) {
  2330  	b, _ := json.Marshal(request)
  2331  	r, err := c.DoApiPost("/actions/dialogs/open", string(b))
  2332  	if err != nil {
  2333  		return false, BuildErrorResponse(r, err)
  2334  	}
  2335  	defer closeBody(r)
  2336  	return CheckStatusOK(r), BuildResponse(r)
  2337  }
  2338  
  2339  // SubmitInteractiveDialog will submit the provided dialog data to the integration
  2340  // configured by the URL. Used with the interactive dialogs integration feature.
  2341  func (c *Client4) SubmitInteractiveDialog(request SubmitDialogRequest) (*SubmitDialogResponse, *Response) {
  2342  	b, _ := json.Marshal(request)
  2343  	r, err := c.DoApiPost("/actions/dialogs/submit", string(b))
  2344  	if err != nil {
  2345  		return nil, BuildErrorResponse(r, err)
  2346  	}
  2347  	defer closeBody(r)
  2348  
  2349  	var resp SubmitDialogResponse
  2350  	json.NewDecoder(r.Body).Decode(&resp)
  2351  	return &resp, BuildResponse(r)
  2352  }
  2353  
  2354  // UploadFile will upload a file to a channel using a multipart request, to be later attached to a post.
  2355  // This method is functionally equivalent to Client4.UploadFileAsRequestBody.
  2356  func (c *Client4) UploadFile(data []byte, channelId string, filename string) (*FileUploadResponse, *Response) {
  2357  	body := &bytes.Buffer{}
  2358  	writer := multipart.NewWriter(body)
  2359  
  2360  	part, err := writer.CreateFormField("channel_id")
  2361  	if err != nil {
  2362  		return nil, &Response{Error: NewAppError("UploadPostAttachment", "model.client.upload_post_attachment.channel_id.app_error", nil, err.Error(), http.StatusBadRequest)}
  2363  	}
  2364  
  2365  	_, err = io.Copy(part, strings.NewReader(channelId))
  2366  	if err != nil {
  2367  		return nil, &Response{Error: NewAppError("UploadPostAttachment", "model.client.upload_post_attachment.channel_id.app_error", nil, err.Error(), http.StatusBadRequest)}
  2368  	}
  2369  
  2370  	part, err = writer.CreateFormFile("files", filename)
  2371  	if err != nil {
  2372  		return nil, &Response{Error: NewAppError("UploadPostAttachment", "model.client.upload_post_attachment.file.app_error", nil, err.Error(), http.StatusBadRequest)}
  2373  	}
  2374  	_, err = io.Copy(part, bytes.NewBuffer(data))
  2375  	if err != nil {
  2376  		return nil, &Response{Error: NewAppError("UploadPostAttachment", "model.client.upload_post_attachment.file.app_error", nil, err.Error(), http.StatusBadRequest)}
  2377  	}
  2378  
  2379  	err = writer.Close()
  2380  	if err != nil {
  2381  		return nil, &Response{Error: NewAppError("UploadPostAttachment", "model.client.upload_post_attachment.writer.app_error", nil, err.Error(), http.StatusBadRequest)}
  2382  	}
  2383  
  2384  	return c.DoUploadFile(c.GetFilesRoute(), body.Bytes(), writer.FormDataContentType())
  2385  }
  2386  
  2387  // UploadFileAsRequestBody will upload a file to a channel as the body of a request, to be later attached
  2388  // to a post. This method is functionally equivalent to Client4.UploadFile.
  2389  func (c *Client4) UploadFileAsRequestBody(data []byte, channelId string, filename string) (*FileUploadResponse, *Response) {
  2390  	return c.DoUploadFile(c.GetFilesRoute()+fmt.Sprintf("?channel_id=%v&filename=%v", url.QueryEscape(channelId), url.QueryEscape(filename)), data, http.DetectContentType(data))
  2391  }
  2392  
  2393  // GetFile gets the bytes for a file by id.
  2394  func (c *Client4) GetFile(fileId string) ([]byte, *Response) {
  2395  	r, appErr := c.DoApiGet(c.GetFileRoute(fileId), "")
  2396  	if appErr != nil {
  2397  		return nil, BuildErrorResponse(r, appErr)
  2398  	}
  2399  	defer closeBody(r)
  2400  
  2401  	data, err := ioutil.ReadAll(r.Body)
  2402  	if err != nil {
  2403  		return nil, BuildErrorResponse(r, NewAppError("GetFile", "model.client.read_file.app_error", nil, err.Error(), r.StatusCode))
  2404  	}
  2405  	return data, BuildResponse(r)
  2406  }
  2407  
  2408  // DownloadFile gets the bytes for a file by id, optionally adding headers to force the browser to download it.
  2409  func (c *Client4) DownloadFile(fileId string, download bool) ([]byte, *Response) {
  2410  	r, appErr := c.DoApiGet(c.GetFileRoute(fileId)+fmt.Sprintf("?download=%v", download), "")
  2411  	if appErr != nil {
  2412  		return nil, BuildErrorResponse(r, appErr)
  2413  	}
  2414  	defer closeBody(r)
  2415  
  2416  	data, err := ioutil.ReadAll(r.Body)
  2417  	if err != nil {
  2418  		return nil, BuildErrorResponse(r, NewAppError("DownloadFile", "model.client.read_file.app_error", nil, err.Error(), r.StatusCode))
  2419  	}
  2420  	return data, BuildResponse(r)
  2421  }
  2422  
  2423  // GetFileThumbnail gets the bytes for a file by id.
  2424  func (c *Client4) GetFileThumbnail(fileId string) ([]byte, *Response) {
  2425  	r, appErr := c.DoApiGet(c.GetFileRoute(fileId)+"/thumbnail", "")
  2426  	if appErr != nil {
  2427  		return nil, BuildErrorResponse(r, appErr)
  2428  	}
  2429  	defer closeBody(r)
  2430  
  2431  	data, err := ioutil.ReadAll(r.Body)
  2432  	if err != nil {
  2433  		return nil, BuildErrorResponse(r, NewAppError("GetFileThumbnail", "model.client.read_file.app_error", nil, err.Error(), r.StatusCode))
  2434  	}
  2435  	return data, BuildResponse(r)
  2436  }
  2437  
  2438  // DownloadFileThumbnail gets the bytes for a file by id, optionally adding headers to force the browser to download it.
  2439  func (c *Client4) DownloadFileThumbnail(fileId string, download bool) ([]byte, *Response) {
  2440  	r, appErr := c.DoApiGet(c.GetFileRoute(fileId)+fmt.Sprintf("/thumbnail?download=%v", download), "")
  2441  	if appErr != nil {
  2442  		return nil, BuildErrorResponse(r, appErr)
  2443  	}
  2444  	defer closeBody(r)
  2445  
  2446  	data, err := ioutil.ReadAll(r.Body)
  2447  	if err != nil {
  2448  		return nil, BuildErrorResponse(r, NewAppError("DownloadFileThumbnail", "model.client.read_file.app_error", nil, err.Error(), r.StatusCode))
  2449  	}
  2450  	return data, BuildResponse(r)
  2451  }
  2452  
  2453  // GetFileLink gets the public link of a file by id.
  2454  func (c *Client4) GetFileLink(fileId string) (string, *Response) {
  2455  	r, err := c.DoApiGet(c.GetFileRoute(fileId)+"/link", "")
  2456  	if err != nil {
  2457  		return "", BuildErrorResponse(r, err)
  2458  	}
  2459  	defer closeBody(r)
  2460  	return MapFromJson(r.Body)["link"], BuildResponse(r)
  2461  }
  2462  
  2463  // GetFilePreview gets the bytes for a file by id.
  2464  func (c *Client4) GetFilePreview(fileId string) ([]byte, *Response) {
  2465  	r, appErr := c.DoApiGet(c.GetFileRoute(fileId)+"/preview", "")
  2466  	if appErr != nil {
  2467  		return nil, BuildErrorResponse(r, appErr)
  2468  	}
  2469  	defer closeBody(r)
  2470  
  2471  	data, err := ioutil.ReadAll(r.Body)
  2472  	if err != nil {
  2473  		return nil, BuildErrorResponse(r, NewAppError("GetFilePreview", "model.client.read_file.app_error", nil, err.Error(), r.StatusCode))
  2474  	}
  2475  	return data, BuildResponse(r)
  2476  }
  2477  
  2478  // DownloadFilePreview gets the bytes for a file by id.
  2479  func (c *Client4) DownloadFilePreview(fileId string, download bool) ([]byte, *Response) {
  2480  	r, appErr := c.DoApiGet(c.GetFileRoute(fileId)+fmt.Sprintf("/preview?download=%v", download), "")
  2481  	if appErr != nil {
  2482  		return nil, BuildErrorResponse(r, appErr)
  2483  	}
  2484  	defer closeBody(r)
  2485  
  2486  	data, err := ioutil.ReadAll(r.Body)
  2487  	if err != nil {
  2488  		return nil, BuildErrorResponse(r, NewAppError("DownloadFilePreview", "model.client.read_file.app_error", nil, err.Error(), r.StatusCode))
  2489  	}
  2490  	return data, BuildResponse(r)
  2491  }
  2492  
  2493  // GetFileInfo gets all the file info objects.
  2494  func (c *Client4) GetFileInfo(fileId string) (*FileInfo, *Response) {
  2495  	r, err := c.DoApiGet(c.GetFileRoute(fileId)+"/info", "")
  2496  	if err != nil {
  2497  		return nil, BuildErrorResponse(r, err)
  2498  	}
  2499  	defer closeBody(r)
  2500  	return FileInfoFromJson(r.Body), BuildResponse(r)
  2501  }
  2502  
  2503  // GetFileInfosForPost gets all the file info objects attached to a post.
  2504  func (c *Client4) GetFileInfosForPost(postId string, etag string) ([]*FileInfo, *Response) {
  2505  	r, err := c.DoApiGet(c.GetPostRoute(postId)+"/files/info", etag)
  2506  	if err != nil {
  2507  		return nil, BuildErrorResponse(r, err)
  2508  	}
  2509  	defer closeBody(r)
  2510  	return FileInfosFromJson(r.Body), BuildResponse(r)
  2511  }
  2512  
  2513  // General/System Section
  2514  
  2515  // GetPing will return ok if the running goRoutines are below the threshold and unhealthy for above.
  2516  func (c *Client4) GetPing() (string, *Response) {
  2517  	r, err := c.DoApiGet(c.GetSystemRoute()+"/ping", "")
  2518  	if r != nil && r.StatusCode == 500 {
  2519  		defer r.Body.Close()
  2520  		return "unhealthy", BuildErrorResponse(r, err)
  2521  	}
  2522  	if err != nil {
  2523  		return "", BuildErrorResponse(r, err)
  2524  	}
  2525  	defer closeBody(r)
  2526  	return MapFromJson(r.Body)["status"], BuildResponse(r)
  2527  }
  2528  
  2529  // TestEmail will attempt to connect to the configured SMTP server.
  2530  func (c *Client4) TestEmail(config *Config) (bool, *Response) {
  2531  	r, err := c.DoApiPost(c.GetTestEmailRoute(), config.ToJson())
  2532  	if err != nil {
  2533  		return false, BuildErrorResponse(r, err)
  2534  	}
  2535  	defer closeBody(r)
  2536  	return CheckStatusOK(r), BuildResponse(r)
  2537  }
  2538  
  2539  // TestS3Connection will attempt to connect to the AWS S3.
  2540  func (c *Client4) TestS3Connection(config *Config) (bool, *Response) {
  2541  	r, err := c.DoApiPost(c.GetTestS3Route(), config.ToJson())
  2542  	if err != nil {
  2543  		return false, BuildErrorResponse(r, err)
  2544  	}
  2545  	defer closeBody(r)
  2546  	return CheckStatusOK(r), BuildResponse(r)
  2547  }
  2548  
  2549  // GetConfig will retrieve the server config with some sanitized items.
  2550  func (c *Client4) GetConfig() (*Config, *Response) {
  2551  	r, err := c.DoApiGet(c.GetConfigRoute(), "")
  2552  	if err != nil {
  2553  		return nil, BuildErrorResponse(r, err)
  2554  	}
  2555  	defer closeBody(r)
  2556  	return ConfigFromJson(r.Body), BuildResponse(r)
  2557  }
  2558  
  2559  // ReloadConfig will reload the server configuration.
  2560  func (c *Client4) ReloadConfig() (bool, *Response) {
  2561  	r, err := c.DoApiPost(c.GetConfigRoute()+"/reload", "")
  2562  	if err != nil {
  2563  		return false, BuildErrorResponse(r, err)
  2564  	}
  2565  	defer closeBody(r)
  2566  	return CheckStatusOK(r), BuildResponse(r)
  2567  }
  2568  
  2569  // GetOldClientConfig will retrieve the parts of the server configuration needed by the
  2570  // client, formatted in the old format.
  2571  func (c *Client4) GetOldClientConfig(etag string) (map[string]string, *Response) {
  2572  	r, err := c.DoApiGet(c.GetConfigRoute()+"/client?format=old", etag)
  2573  	if err != nil {
  2574  		return nil, BuildErrorResponse(r, err)
  2575  	}
  2576  	defer closeBody(r)
  2577  	return MapFromJson(r.Body), BuildResponse(r)
  2578  }
  2579  
  2580  // GetEnvironmentConfig will retrieve a map mirroring the server configuration where fields
  2581  // are set to true if the corresponding config setting is set through an environment variable.
  2582  // Settings that haven't been set through environment variables will be missing from the map.
  2583  func (c *Client4) GetEnvironmentConfig() (map[string]interface{}, *Response) {
  2584  	r, err := c.DoApiGet(c.GetConfigRoute()+"/environment", "")
  2585  	if err != nil {
  2586  		return nil, BuildErrorResponse(r, err)
  2587  	}
  2588  	defer closeBody(r)
  2589  	return StringInterfaceFromJson(r.Body), BuildResponse(r)
  2590  }
  2591  
  2592  // GetOldClientLicense will retrieve the parts of the server license needed by the
  2593  // client, formatted in the old format.
  2594  func (c *Client4) GetOldClientLicense(etag string) (map[string]string, *Response) {
  2595  	r, err := c.DoApiGet(c.GetLicenseRoute()+"/client?format=old", etag)
  2596  	if err != nil {
  2597  		return nil, BuildErrorResponse(r, err)
  2598  	}
  2599  	defer closeBody(r)
  2600  	return MapFromJson(r.Body), BuildResponse(r)
  2601  }
  2602  
  2603  // DatabaseRecycle will recycle the connections. Discard current connection and get new one.
  2604  func (c *Client4) DatabaseRecycle() (bool, *Response) {
  2605  	r, err := c.DoApiPost(c.GetDatabaseRoute()+"/recycle", "")
  2606  	if err != nil {
  2607  		return false, BuildErrorResponse(r, err)
  2608  	}
  2609  	defer closeBody(r)
  2610  	return CheckStatusOK(r), BuildResponse(r)
  2611  }
  2612  
  2613  // InvalidateCaches will purge the cache and can affect the performance while is cleaning.
  2614  func (c *Client4) InvalidateCaches() (bool, *Response) {
  2615  	r, err := c.DoApiPost(c.GetCacheRoute()+"/invalidate", "")
  2616  	if err != nil {
  2617  		return false, BuildErrorResponse(r, err)
  2618  	}
  2619  	defer closeBody(r)
  2620  	return CheckStatusOK(r), BuildResponse(r)
  2621  }
  2622  
  2623  // UpdateConfig will update the server configuration.
  2624  func (c *Client4) UpdateConfig(config *Config) (*Config, *Response) {
  2625  	r, err := c.DoApiPut(c.GetConfigRoute(), config.ToJson())
  2626  	if err != nil {
  2627  		return nil, BuildErrorResponse(r, err)
  2628  	}
  2629  	defer closeBody(r)
  2630  	return ConfigFromJson(r.Body), BuildResponse(r)
  2631  }
  2632  
  2633  // UploadLicenseFile will add a license file to the system.
  2634  func (c *Client4) UploadLicenseFile(data []byte) (bool, *Response) {
  2635  	body := &bytes.Buffer{}
  2636  	writer := multipart.NewWriter(body)
  2637  
  2638  	part, err := writer.CreateFormFile("license", "test-license.mattermost-license")
  2639  	if err != nil {
  2640  		return false, &Response{Error: NewAppError("UploadLicenseFile", "model.client.set_profile_user.no_file.app_error", nil, err.Error(), http.StatusBadRequest)}
  2641  	}
  2642  
  2643  	if _, err = io.Copy(part, bytes.NewBuffer(data)); err != nil {
  2644  		return false, &Response{Error: NewAppError("UploadLicenseFile", "model.client.set_profile_user.no_file.app_error", nil, err.Error(), http.StatusBadRequest)}
  2645  	}
  2646  
  2647  	if err = writer.Close(); err != nil {
  2648  		return false, &Response{Error: NewAppError("UploadLicenseFile", "model.client.set_profile_user.writer.app_error", nil, err.Error(), http.StatusBadRequest)}
  2649  	}
  2650  
  2651  	rq, err := http.NewRequest("POST", c.ApiUrl+c.GetLicenseRoute(), bytes.NewReader(body.Bytes()))
  2652  	if err != nil {
  2653  		return false, &Response{Error: NewAppError("UploadLicenseFile", "model.client.connecting.app_error", nil, err.Error(), http.StatusBadRequest)}
  2654  	}
  2655  	rq.Header.Set("Content-Type", writer.FormDataContentType())
  2656  
  2657  	if len(c.AuthToken) > 0 {
  2658  		rq.Header.Set(HEADER_AUTH, c.AuthType+" "+c.AuthToken)
  2659  	}
  2660  
  2661  	rp, err := c.HttpClient.Do(rq)
  2662  	if err != nil || rp == nil {
  2663  		return false, &Response{StatusCode: http.StatusForbidden, Error: NewAppError(c.GetLicenseRoute(), "model.client.connecting.app_error", nil, err.Error(), http.StatusForbidden)}
  2664  	}
  2665  	defer closeBody(rp)
  2666  
  2667  	if rp.StatusCode >= 300 {
  2668  		return false, BuildErrorResponse(rp, AppErrorFromJson(rp.Body))
  2669  	}
  2670  
  2671  	return CheckStatusOK(rp), BuildResponse(rp)
  2672  }
  2673  
  2674  // RemoveLicenseFile will remove the server license it exists. Note that this will
  2675  // disable all enterprise features.
  2676  func (c *Client4) RemoveLicenseFile() (bool, *Response) {
  2677  	r, err := c.DoApiDelete(c.GetLicenseRoute())
  2678  	if err != nil {
  2679  		return false, BuildErrorResponse(r, err)
  2680  	}
  2681  	defer closeBody(r)
  2682  	return CheckStatusOK(r), BuildResponse(r)
  2683  }
  2684  
  2685  // GetAnalyticsOld will retrieve analytics using the old format. New format is not
  2686  // available but the "/analytics" endpoint is reserved for it. The "name" argument is optional
  2687  // and defaults to "standard". The "teamId" argument is optional and will limit results
  2688  // to a specific team.
  2689  func (c *Client4) GetAnalyticsOld(name, teamId string) (AnalyticsRows, *Response) {
  2690  	query := fmt.Sprintf("?name=%v&team_id=%v", name, teamId)
  2691  	r, err := c.DoApiGet(c.GetAnalyticsRoute()+"/old"+query, "")
  2692  	if err != nil {
  2693  		return nil, BuildErrorResponse(r, err)
  2694  	}
  2695  	defer closeBody(r)
  2696  	return AnalyticsRowsFromJson(r.Body), BuildResponse(r)
  2697  }
  2698  
  2699  // Webhooks Section
  2700  
  2701  // CreateIncomingWebhook creates an incoming webhook for a channel.
  2702  func (c *Client4) CreateIncomingWebhook(hook *IncomingWebhook) (*IncomingWebhook, *Response) {
  2703  	r, err := c.DoApiPost(c.GetIncomingWebhooksRoute(), hook.ToJson())
  2704  	if err != nil {
  2705  		return nil, BuildErrorResponse(r, err)
  2706  	}
  2707  	defer closeBody(r)
  2708  	return IncomingWebhookFromJson(r.Body), BuildResponse(r)
  2709  }
  2710  
  2711  // UpdateIncomingWebhook updates an incoming webhook for a channel.
  2712  func (c *Client4) UpdateIncomingWebhook(hook *IncomingWebhook) (*IncomingWebhook, *Response) {
  2713  	r, err := c.DoApiPut(c.GetIncomingWebhookRoute(hook.Id), hook.ToJson())
  2714  	if err != nil {
  2715  		return nil, BuildErrorResponse(r, err)
  2716  	}
  2717  	defer closeBody(r)
  2718  	return IncomingWebhookFromJson(r.Body), BuildResponse(r)
  2719  }
  2720  
  2721  // GetIncomingWebhooks returns a page of incoming webhooks on the system. Page counting starts at 0.
  2722  func (c *Client4) GetIncomingWebhooks(page int, perPage int, etag string) ([]*IncomingWebhook, *Response) {
  2723  	query := fmt.Sprintf("?page=%v&per_page=%v", page, perPage)
  2724  	r, err := c.DoApiGet(c.GetIncomingWebhooksRoute()+query, etag)
  2725  	if err != nil {
  2726  		return nil, BuildErrorResponse(r, err)
  2727  	}
  2728  	defer closeBody(r)
  2729  	return IncomingWebhookListFromJson(r.Body), BuildResponse(r)
  2730  }
  2731  
  2732  // GetIncomingWebhooksForTeam returns a page of incoming webhooks for a team. Page counting starts at 0.
  2733  func (c *Client4) GetIncomingWebhooksForTeam(teamId string, page int, perPage int, etag string) ([]*IncomingWebhook, *Response) {
  2734  	query := fmt.Sprintf("?page=%v&per_page=%v&team_id=%v", page, perPage, teamId)
  2735  	r, err := c.DoApiGet(c.GetIncomingWebhooksRoute()+query, etag)
  2736  	if err != nil {
  2737  		return nil, BuildErrorResponse(r, err)
  2738  	}
  2739  	defer closeBody(r)
  2740  	return IncomingWebhookListFromJson(r.Body), BuildResponse(r)
  2741  }
  2742  
  2743  // GetIncomingWebhook returns an Incoming webhook given the hook ID.
  2744  func (c *Client4) GetIncomingWebhook(hookID string, etag string) (*IncomingWebhook, *Response) {
  2745  	r, err := c.DoApiGet(c.GetIncomingWebhookRoute(hookID), etag)
  2746  	if err != nil {
  2747  		return nil, BuildErrorResponse(r, err)
  2748  	}
  2749  	defer closeBody(r)
  2750  	return IncomingWebhookFromJson(r.Body), BuildResponse(r)
  2751  }
  2752  
  2753  // DeleteIncomingWebhook deletes and Incoming Webhook given the hook ID.
  2754  func (c *Client4) DeleteIncomingWebhook(hookID string) (bool, *Response) {
  2755  	r, err := c.DoApiDelete(c.GetIncomingWebhookRoute(hookID))
  2756  	if err != nil {
  2757  		return false, BuildErrorResponse(r, err)
  2758  	}
  2759  	defer closeBody(r)
  2760  	return CheckStatusOK(r), BuildResponse(r)
  2761  }
  2762  
  2763  // CreateOutgoingWebhook creates an outgoing webhook for a team or channel.
  2764  func (c *Client4) CreateOutgoingWebhook(hook *OutgoingWebhook) (*OutgoingWebhook, *Response) {
  2765  	r, err := c.DoApiPost(c.GetOutgoingWebhooksRoute(), hook.ToJson())
  2766  	if err != nil {
  2767  		return nil, BuildErrorResponse(r, err)
  2768  	}
  2769  	defer closeBody(r)
  2770  	return OutgoingWebhookFromJson(r.Body), BuildResponse(r)
  2771  }
  2772  
  2773  // UpdateOutgoingWebhook creates an outgoing webhook for a team or channel.
  2774  func (c *Client4) UpdateOutgoingWebhook(hook *OutgoingWebhook) (*OutgoingWebhook, *Response) {
  2775  	r, err := c.DoApiPut(c.GetOutgoingWebhookRoute(hook.Id), hook.ToJson())
  2776  	if err != nil {
  2777  		return nil, BuildErrorResponse(r, err)
  2778  	}
  2779  	defer closeBody(r)
  2780  	return OutgoingWebhookFromJson(r.Body), BuildResponse(r)
  2781  }
  2782  
  2783  // GetOutgoingWebhooks returns a page of outgoing webhooks on the system. Page counting starts at 0.
  2784  func (c *Client4) GetOutgoingWebhooks(page int, perPage int, etag string) ([]*OutgoingWebhook, *Response) {
  2785  	query := fmt.Sprintf("?page=%v&per_page=%v", page, perPage)
  2786  	r, err := c.DoApiGet(c.GetOutgoingWebhooksRoute()+query, etag)
  2787  	if err != nil {
  2788  		return nil, BuildErrorResponse(r, err)
  2789  	}
  2790  	defer closeBody(r)
  2791  	return OutgoingWebhookListFromJson(r.Body), BuildResponse(r)
  2792  }
  2793  
  2794  // GetOutgoingWebhook outgoing webhooks on the system requested by Hook Id.
  2795  func (c *Client4) GetOutgoingWebhook(hookId string) (*OutgoingWebhook, *Response) {
  2796  	r, err := c.DoApiGet(c.GetOutgoingWebhookRoute(hookId), "")
  2797  	if err != nil {
  2798  		return nil, BuildErrorResponse(r, err)
  2799  	}
  2800  	defer closeBody(r)
  2801  	return OutgoingWebhookFromJson(r.Body), BuildResponse(r)
  2802  }
  2803  
  2804  // GetOutgoingWebhooksForChannel returns a page of outgoing webhooks for a channel. Page counting starts at 0.
  2805  func (c *Client4) GetOutgoingWebhooksForChannel(channelId string, page int, perPage int, etag string) ([]*OutgoingWebhook, *Response) {
  2806  	query := fmt.Sprintf("?page=%v&per_page=%v&channel_id=%v", page, perPage, channelId)
  2807  	r, err := c.DoApiGet(c.GetOutgoingWebhooksRoute()+query, etag)
  2808  	if err != nil {
  2809  		return nil, BuildErrorResponse(r, err)
  2810  	}
  2811  	defer closeBody(r)
  2812  	return OutgoingWebhookListFromJson(r.Body), BuildResponse(r)
  2813  }
  2814  
  2815  // GetOutgoingWebhooksForTeam returns a page of outgoing webhooks for a team. Page counting starts at 0.
  2816  func (c *Client4) GetOutgoingWebhooksForTeam(teamId string, page int, perPage int, etag string) ([]*OutgoingWebhook, *Response) {
  2817  	query := fmt.Sprintf("?page=%v&per_page=%v&team_id=%v", page, perPage, teamId)
  2818  	r, err := c.DoApiGet(c.GetOutgoingWebhooksRoute()+query, etag)
  2819  	if err != nil {
  2820  		return nil, BuildErrorResponse(r, err)
  2821  	}
  2822  	defer closeBody(r)
  2823  	return OutgoingWebhookListFromJson(r.Body), BuildResponse(r)
  2824  }
  2825  
  2826  // RegenOutgoingHookToken regenerate the outgoing webhook token.
  2827  func (c *Client4) RegenOutgoingHookToken(hookId string) (*OutgoingWebhook, *Response) {
  2828  	r, err := c.DoApiPost(c.GetOutgoingWebhookRoute(hookId)+"/regen_token", "")
  2829  	if err != nil {
  2830  		return nil, BuildErrorResponse(r, err)
  2831  	}
  2832  	defer closeBody(r)
  2833  	return OutgoingWebhookFromJson(r.Body), BuildResponse(r)
  2834  }
  2835  
  2836  // DeleteOutgoingWebhook delete the outgoing webhook on the system requested by Hook Id.
  2837  func (c *Client4) DeleteOutgoingWebhook(hookId string) (bool, *Response) {
  2838  	r, err := c.DoApiDelete(c.GetOutgoingWebhookRoute(hookId))
  2839  	if err != nil {
  2840  		return false, BuildErrorResponse(r, err)
  2841  	}
  2842  	defer closeBody(r)
  2843  	return CheckStatusOK(r), BuildResponse(r)
  2844  }
  2845  
  2846  // Preferences Section
  2847  
  2848  // GetPreferences returns the user's preferences.
  2849  func (c *Client4) GetPreferences(userId string) (Preferences, *Response) {
  2850  	r, err := c.DoApiGet(c.GetPreferencesRoute(userId), "")
  2851  	if err != nil {
  2852  		return nil, BuildErrorResponse(r, err)
  2853  	}
  2854  	defer closeBody(r)
  2855  	preferences, _ := PreferencesFromJson(r.Body)
  2856  	return preferences, BuildResponse(r)
  2857  }
  2858  
  2859  // UpdatePreferences saves the user's preferences.
  2860  func (c *Client4) UpdatePreferences(userId string, preferences *Preferences) (bool, *Response) {
  2861  	r, err := c.DoApiPut(c.GetPreferencesRoute(userId), preferences.ToJson())
  2862  	if err != nil {
  2863  		return false, BuildErrorResponse(r, err)
  2864  	}
  2865  	defer closeBody(r)
  2866  	return true, BuildResponse(r)
  2867  }
  2868  
  2869  // DeletePreferences deletes the user's preferences.
  2870  func (c *Client4) DeletePreferences(userId string, preferences *Preferences) (bool, *Response) {
  2871  	r, err := c.DoApiPost(c.GetPreferencesRoute(userId)+"/delete", preferences.ToJson())
  2872  	if err != nil {
  2873  		return false, BuildErrorResponse(r, err)
  2874  	}
  2875  	defer closeBody(r)
  2876  	return true, BuildResponse(r)
  2877  }
  2878  
  2879  // GetPreferencesByCategory returns the user's preferences from the provided category string.
  2880  func (c *Client4) GetPreferencesByCategory(userId string, category string) (Preferences, *Response) {
  2881  	url := fmt.Sprintf(c.GetPreferencesRoute(userId)+"/%s", category)
  2882  	r, err := c.DoApiGet(url, "")
  2883  	if err != nil {
  2884  		return nil, BuildErrorResponse(r, err)
  2885  	}
  2886  	defer closeBody(r)
  2887  	preferences, _ := PreferencesFromJson(r.Body)
  2888  	return preferences, BuildResponse(r)
  2889  }
  2890  
  2891  // GetPreferenceByCategoryAndName returns the user's preferences from the provided category and preference name string.
  2892  func (c *Client4) GetPreferenceByCategoryAndName(userId string, category string, preferenceName string) (*Preference, *Response) {
  2893  	url := fmt.Sprintf(c.GetPreferencesRoute(userId)+"/%s/name/%v", category, preferenceName)
  2894  	r, err := c.DoApiGet(url, "")
  2895  	if err != nil {
  2896  		return nil, BuildErrorResponse(r, err)
  2897  	}
  2898  	defer closeBody(r)
  2899  	return PreferenceFromJson(r.Body), BuildResponse(r)
  2900  }
  2901  
  2902  // SAML Section
  2903  
  2904  // GetSamlMetadata returns metadata for the SAML configuration.
  2905  func (c *Client4) GetSamlMetadata() (string, *Response) {
  2906  	r, err := c.DoApiGet(c.GetSamlRoute()+"/metadata", "")
  2907  	if err != nil {
  2908  		return "", BuildErrorResponse(r, err)
  2909  	}
  2910  	defer closeBody(r)
  2911  	buf := new(bytes.Buffer)
  2912  	_, _ = buf.ReadFrom(r.Body)
  2913  	return buf.String(), BuildResponse(r)
  2914  }
  2915  
  2916  func samlFileToMultipart(data []byte, filename string) ([]byte, *multipart.Writer, error) {
  2917  	body := &bytes.Buffer{}
  2918  	writer := multipart.NewWriter(body)
  2919  
  2920  	part, err := writer.CreateFormFile("certificate", filename)
  2921  	if err != nil {
  2922  		return nil, nil, err
  2923  	}
  2924  
  2925  	if _, err = io.Copy(part, bytes.NewBuffer(data)); err != nil {
  2926  		return nil, nil, err
  2927  	}
  2928  
  2929  	if err := writer.Close(); err != nil {
  2930  		return nil, nil, err
  2931  	}
  2932  
  2933  	return body.Bytes(), writer, nil
  2934  }
  2935  
  2936  // UploadSamlIdpCertificate will upload an IDP certificate for SAML and set the config to use it.
  2937  func (c *Client4) UploadSamlIdpCertificate(data []byte, filename string) (bool, *Response) {
  2938  	body, writer, err := samlFileToMultipart(data, filename)
  2939  	if err != nil {
  2940  		return false, &Response{Error: NewAppError("UploadSamlIdpCertificate", "model.client.upload_saml_cert.app_error", nil, err.Error(), http.StatusBadRequest)}
  2941  	}
  2942  
  2943  	_, resp := c.DoUploadFile(c.GetSamlRoute()+"/certificate/idp", body, writer.FormDataContentType())
  2944  	return resp.Error == nil, resp
  2945  }
  2946  
  2947  // UploadSamlPublicCertificate will upload a public certificate for SAML and set the config to use it.
  2948  func (c *Client4) UploadSamlPublicCertificate(data []byte, filename string) (bool, *Response) {
  2949  	body, writer, err := samlFileToMultipart(data, filename)
  2950  	if err != nil {
  2951  		return false, &Response{Error: NewAppError("UploadSamlPublicCertificate", "model.client.upload_saml_cert.app_error", nil, err.Error(), http.StatusBadRequest)}
  2952  	}
  2953  
  2954  	_, resp := c.DoUploadFile(c.GetSamlRoute()+"/certificate/public", body, writer.FormDataContentType())
  2955  	return resp.Error == nil, resp
  2956  }
  2957  
  2958  // UploadSamlPrivateCertificate will upload a private key for SAML and set the config to use it.
  2959  func (c *Client4) UploadSamlPrivateCertificate(data []byte, filename string) (bool, *Response) {
  2960  	body, writer, err := samlFileToMultipart(data, filename)
  2961  	if err != nil {
  2962  		return false, &Response{Error: NewAppError("UploadSamlPrivateCertificate", "model.client.upload_saml_cert.app_error", nil, err.Error(), http.StatusBadRequest)}
  2963  	}
  2964  
  2965  	_, resp := c.DoUploadFile(c.GetSamlRoute()+"/certificate/private", body, writer.FormDataContentType())
  2966  	return resp.Error == nil, resp
  2967  }
  2968  
  2969  // DeleteSamlIdpCertificate deletes the SAML IDP certificate from the server and updates the config to not use it and disable SAML.
  2970  func (c *Client4) DeleteSamlIdpCertificate() (bool, *Response) {
  2971  	r, err := c.DoApiDelete(c.GetSamlRoute() + "/certificate/idp")
  2972  	if err != nil {
  2973  		return false, BuildErrorResponse(r, err)
  2974  	}
  2975  	defer closeBody(r)
  2976  	return CheckStatusOK(r), BuildResponse(r)
  2977  }
  2978  
  2979  // DeleteSamlPublicCertificate deletes the SAML IDP certificate from the server and updates the config to not use it and disable SAML.
  2980  func (c *Client4) DeleteSamlPublicCertificate() (bool, *Response) {
  2981  	r, err := c.DoApiDelete(c.GetSamlRoute() + "/certificate/public")
  2982  	if err != nil {
  2983  		return false, BuildErrorResponse(r, err)
  2984  	}
  2985  	defer closeBody(r)
  2986  	return CheckStatusOK(r), BuildResponse(r)
  2987  }
  2988  
  2989  // DeleteSamlPrivateCertificate deletes the SAML IDP certificate from the server and updates the config to not use it and disable SAML.
  2990  func (c *Client4) DeleteSamlPrivateCertificate() (bool, *Response) {
  2991  	r, err := c.DoApiDelete(c.GetSamlRoute() + "/certificate/private")
  2992  	if err != nil {
  2993  		return false, BuildErrorResponse(r, err)
  2994  	}
  2995  	defer closeBody(r)
  2996  	return CheckStatusOK(r), BuildResponse(r)
  2997  }
  2998  
  2999  // GetSamlCertificateStatus returns metadata for the SAML configuration.
  3000  func (c *Client4) GetSamlCertificateStatus() (*SamlCertificateStatus, *Response) {
  3001  	r, err := c.DoApiGet(c.GetSamlRoute()+"/certificate/status", "")
  3002  	if err != nil {
  3003  		return nil, BuildErrorResponse(r, err)
  3004  	}
  3005  	defer closeBody(r)
  3006  	return SamlCertificateStatusFromJson(r.Body), BuildResponse(r)
  3007  }
  3008  
  3009  // Compliance Section
  3010  
  3011  // CreateComplianceReport creates an incoming webhook for a channel.
  3012  func (c *Client4) CreateComplianceReport(report *Compliance) (*Compliance, *Response) {
  3013  	r, err := c.DoApiPost(c.GetComplianceReportsRoute(), report.ToJson())
  3014  	if err != nil {
  3015  		return nil, BuildErrorResponse(r, err)
  3016  	}
  3017  	defer closeBody(r)
  3018  	return ComplianceFromJson(r.Body), BuildResponse(r)
  3019  }
  3020  
  3021  // GetComplianceReports returns list of compliance reports.
  3022  func (c *Client4) GetComplianceReports(page, perPage int) (Compliances, *Response) {
  3023  	query := fmt.Sprintf("?page=%v&per_page=%v", page, perPage)
  3024  	r, err := c.DoApiGet(c.GetComplianceReportsRoute()+query, "")
  3025  	if err != nil {
  3026  		return nil, BuildErrorResponse(r, err)
  3027  	}
  3028  	defer closeBody(r)
  3029  	return CompliancesFromJson(r.Body), BuildResponse(r)
  3030  }
  3031  
  3032  // GetComplianceReport returns a compliance report.
  3033  func (c *Client4) GetComplianceReport(reportId string) (*Compliance, *Response) {
  3034  	r, err := c.DoApiGet(c.GetComplianceReportRoute(reportId), "")
  3035  	if err != nil {
  3036  		return nil, BuildErrorResponse(r, err)
  3037  	}
  3038  	defer closeBody(r)
  3039  	return ComplianceFromJson(r.Body), BuildResponse(r)
  3040  }
  3041  
  3042  // DownloadComplianceReport returns a full compliance report as a file.
  3043  func (c *Client4) DownloadComplianceReport(reportId string) ([]byte, *Response) {
  3044  	rq, err := http.NewRequest("GET", c.ApiUrl+c.GetComplianceReportRoute(reportId), nil)
  3045  	if err != nil {
  3046  		return nil, &Response{Error: NewAppError("DownloadComplianceReport", "model.client.connecting.app_error", nil, err.Error(), http.StatusBadRequest)}
  3047  	}
  3048  
  3049  	if len(c.AuthToken) > 0 {
  3050  		rq.Header.Set(HEADER_AUTH, "BEARER "+c.AuthToken)
  3051  	}
  3052  
  3053  	rp, err := c.HttpClient.Do(rq)
  3054  	if err != nil || rp == nil {
  3055  		return nil, &Response{Error: NewAppError("DownloadComplianceReport", "model.client.connecting.app_error", nil, err.Error(), http.StatusBadRequest)}
  3056  	}
  3057  	defer closeBody(rp)
  3058  
  3059  	if rp.StatusCode >= 300 {
  3060  		return nil, BuildErrorResponse(rp, AppErrorFromJson(rp.Body))
  3061  	}
  3062  
  3063  	data, err := ioutil.ReadAll(rp.Body)
  3064  	if err != nil {
  3065  		return nil, BuildErrorResponse(rp, NewAppError("DownloadComplianceReport", "model.client.read_file.app_error", nil, err.Error(), rp.StatusCode))
  3066  	}
  3067  
  3068  	return data, BuildResponse(rp)
  3069  }
  3070  
  3071  // Cluster Section
  3072  
  3073  // GetClusterStatus returns the status of all the configured cluster nodes.
  3074  func (c *Client4) GetClusterStatus() ([]*ClusterInfo, *Response) {
  3075  	r, err := c.DoApiGet(c.GetClusterRoute()+"/status", "")
  3076  	if err != nil {
  3077  		return nil, BuildErrorResponse(r, err)
  3078  	}
  3079  	defer closeBody(r)
  3080  	return ClusterInfosFromJson(r.Body), BuildResponse(r)
  3081  }
  3082  
  3083  // LDAP Section
  3084  
  3085  // SyncLdap will force a sync with the configured LDAP server.
  3086  func (c *Client4) SyncLdap() (bool, *Response) {
  3087  	r, err := c.DoApiPost(c.GetLdapRoute()+"/sync", "")
  3088  	if err != nil {
  3089  		return false, BuildErrorResponse(r, err)
  3090  	}
  3091  	defer closeBody(r)
  3092  	return CheckStatusOK(r), BuildResponse(r)
  3093  }
  3094  
  3095  // TestLdap will attempt to connect to the configured LDAP server and return OK if configured
  3096  // correctly.
  3097  func (c *Client4) TestLdap() (bool, *Response) {
  3098  	r, err := c.DoApiPost(c.GetLdapRoute()+"/test", "")
  3099  	if err != nil {
  3100  		return false, BuildErrorResponse(r, err)
  3101  	}
  3102  	defer closeBody(r)
  3103  	return CheckStatusOK(r), BuildResponse(r)
  3104  }
  3105  
  3106  // GetLdapGroups retrieves the immediate child groups of the given parent group.
  3107  func (c *Client4) GetLdapGroups() ([]*Group, *Response) {
  3108  	path := fmt.Sprintf("%s/groups", c.GetLdapRoute())
  3109  
  3110  	r, appErr := c.DoApiGet(path, "")
  3111  	if appErr != nil {
  3112  		return nil, BuildErrorResponse(r, appErr)
  3113  	}
  3114  	defer closeBody(r)
  3115  
  3116  	return GroupsFromJson(r.Body), BuildResponse(r)
  3117  }
  3118  
  3119  // LinkLdapGroup creates or undeletes a Mattermost group and associates it to the given LDAP group DN.
  3120  func (c *Client4) LinkLdapGroup(dn string) (*Group, *Response) {
  3121  	path := fmt.Sprintf("%s/groups/%s/link", c.GetLdapRoute(), dn)
  3122  
  3123  	r, appErr := c.DoApiPost(path, "")
  3124  	if appErr != nil {
  3125  		return nil, BuildErrorResponse(r, appErr)
  3126  	}
  3127  	defer closeBody(r)
  3128  
  3129  	return GroupFromJson(r.Body), BuildResponse(r)
  3130  }
  3131  
  3132  // UnlinkLdapGroup deletes the Mattermost group associated with the given LDAP group DN.
  3133  func (c *Client4) UnlinkLdapGroup(dn string) (*Group, *Response) {
  3134  	path := fmt.Sprintf("%s/groups/%s/link", c.GetLdapRoute(), dn)
  3135  
  3136  	r, appErr := c.DoApiDelete(path)
  3137  	if appErr != nil {
  3138  		return nil, BuildErrorResponse(r, appErr)
  3139  	}
  3140  	defer closeBody(r)
  3141  
  3142  	return GroupFromJson(r.Body), BuildResponse(r)
  3143  }
  3144  
  3145  // Audits Section
  3146  
  3147  // GetAudits returns a list of audits for the whole system.
  3148  func (c *Client4) GetAudits(page int, perPage int, etag string) (Audits, *Response) {
  3149  	query := fmt.Sprintf("?page=%v&per_page=%v", page, perPage)
  3150  	r, err := c.DoApiGet("/audits"+query, etag)
  3151  	if err != nil {
  3152  		return nil, BuildErrorResponse(r, err)
  3153  	}
  3154  	defer closeBody(r)
  3155  	return AuditsFromJson(r.Body), BuildResponse(r)
  3156  }
  3157  
  3158  // Brand Section
  3159  
  3160  // GetBrandImage retrieves the previously uploaded brand image.
  3161  func (c *Client4) GetBrandImage() ([]byte, *Response) {
  3162  	r, appErr := c.DoApiGet(c.GetBrandRoute()+"/image", "")
  3163  	if appErr != nil {
  3164  		return nil, BuildErrorResponse(r, appErr)
  3165  	}
  3166  	defer closeBody(r)
  3167  
  3168  	if r.StatusCode >= 300 {
  3169  		return nil, BuildErrorResponse(r, AppErrorFromJson(r.Body))
  3170  	}
  3171  
  3172  	data, err := ioutil.ReadAll(r.Body)
  3173  	if err != nil {
  3174  		return nil, BuildErrorResponse(r, NewAppError("GetBrandImage", "model.client.read_file.app_error", nil, err.Error(), r.StatusCode))
  3175  	}
  3176  
  3177  	return data, BuildResponse(r)
  3178  }
  3179  
  3180  // DeleteBrandImage delets the brand image for the system.
  3181  func (c *Client4) DeleteBrandImage() *Response {
  3182  	r, err := c.DoApiDelete(c.GetBrandRoute() + "/image")
  3183  	if err != nil {
  3184  		return BuildErrorResponse(r, err)
  3185  	}
  3186  	return BuildResponse(r)
  3187  }
  3188  
  3189  // UploadBrandImage sets the brand image for the system.
  3190  func (c *Client4) UploadBrandImage(data []byte) (bool, *Response) {
  3191  	body := &bytes.Buffer{}
  3192  	writer := multipart.NewWriter(body)
  3193  
  3194  	part, err := writer.CreateFormFile("image", "brand.png")
  3195  	if err != nil {
  3196  		return false, &Response{Error: NewAppError("UploadBrandImage", "model.client.set_profile_user.no_file.app_error", nil, err.Error(), http.StatusBadRequest)}
  3197  	}
  3198  
  3199  	if _, err = io.Copy(part, bytes.NewBuffer(data)); err != nil {
  3200  		return false, &Response{Error: NewAppError("UploadBrandImage", "model.client.set_profile_user.no_file.app_error", nil, err.Error(), http.StatusBadRequest)}
  3201  	}
  3202  
  3203  	if err = writer.Close(); err != nil {
  3204  		return false, &Response{Error: NewAppError("UploadBrandImage", "model.client.set_profile_user.writer.app_error", nil, err.Error(), http.StatusBadRequest)}
  3205  	}
  3206  
  3207  	rq, err := http.NewRequest("POST", c.ApiUrl+c.GetBrandRoute()+"/image", bytes.NewReader(body.Bytes()))
  3208  	if err != nil {
  3209  		return false, &Response{Error: NewAppError("UploadBrandImage", "model.client.connecting.app_error", nil, err.Error(), http.StatusBadRequest)}
  3210  	}
  3211  	rq.Header.Set("Content-Type", writer.FormDataContentType())
  3212  
  3213  	if len(c.AuthToken) > 0 {
  3214  		rq.Header.Set(HEADER_AUTH, c.AuthType+" "+c.AuthToken)
  3215  	}
  3216  
  3217  	rp, err := c.HttpClient.Do(rq)
  3218  	if err != nil || rp == nil {
  3219  		return false, &Response{StatusCode: http.StatusForbidden, Error: NewAppError(c.GetBrandRoute()+"/image", "model.client.connecting.app_error", nil, err.Error(), http.StatusForbidden)}
  3220  	}
  3221  	defer closeBody(rp)
  3222  
  3223  	if rp.StatusCode >= 300 {
  3224  		return false, BuildErrorResponse(rp, AppErrorFromJson(rp.Body))
  3225  	}
  3226  
  3227  	return CheckStatusOK(rp), BuildResponse(rp)
  3228  }
  3229  
  3230  // Logs Section
  3231  
  3232  // GetLogs page of logs as a string array.
  3233  func (c *Client4) GetLogs(page, perPage int) ([]string, *Response) {
  3234  	query := fmt.Sprintf("?page=%v&logs_per_page=%v", page, perPage)
  3235  	r, err := c.DoApiGet("/logs"+query, "")
  3236  	if err != nil {
  3237  		return nil, BuildErrorResponse(r, err)
  3238  	}
  3239  	defer closeBody(r)
  3240  	return ArrayFromJson(r.Body), BuildResponse(r)
  3241  }
  3242  
  3243  // PostLog is a convenience Web Service call so clients can log messages into
  3244  // the server-side logs. For example we typically log javascript error messages
  3245  // into the server-side. It returns the log message if the logging was successful.
  3246  func (c *Client4) PostLog(message map[string]string) (map[string]string, *Response) {
  3247  	r, err := c.DoApiPost("/logs", MapToJson(message))
  3248  	if err != nil {
  3249  		return nil, BuildErrorResponse(r, err)
  3250  	}
  3251  	defer closeBody(r)
  3252  	return MapFromJson(r.Body), BuildResponse(r)
  3253  }
  3254  
  3255  // OAuth Section
  3256  
  3257  // CreateOAuthApp will register a new OAuth 2.0 client application with Mattermost acting as an OAuth 2.0 service provider.
  3258  func (c *Client4) CreateOAuthApp(app *OAuthApp) (*OAuthApp, *Response) {
  3259  	r, err := c.DoApiPost(c.GetOAuthAppsRoute(), app.ToJson())
  3260  	if err != nil {
  3261  		return nil, BuildErrorResponse(r, err)
  3262  	}
  3263  	defer closeBody(r)
  3264  	return OAuthAppFromJson(r.Body), BuildResponse(r)
  3265  }
  3266  
  3267  // UpdateOAuthApp updates a page of registered OAuth 2.0 client applications with Mattermost acting as an OAuth 2.0 service provider.
  3268  func (c *Client4) UpdateOAuthApp(app *OAuthApp) (*OAuthApp, *Response) {
  3269  	r, err := c.DoApiPut(c.GetOAuthAppRoute(app.Id), app.ToJson())
  3270  	if err != nil {
  3271  		return nil, BuildErrorResponse(r, err)
  3272  	}
  3273  	defer closeBody(r)
  3274  	return OAuthAppFromJson(r.Body), BuildResponse(r)
  3275  }
  3276  
  3277  // GetOAuthApps gets a page of registered OAuth 2.0 client applications with Mattermost acting as an OAuth 2.0 service provider.
  3278  func (c *Client4) GetOAuthApps(page, perPage int) ([]*OAuthApp, *Response) {
  3279  	query := fmt.Sprintf("?page=%v&per_page=%v", page, perPage)
  3280  	r, err := c.DoApiGet(c.GetOAuthAppsRoute()+query, "")
  3281  	if err != nil {
  3282  		return nil, BuildErrorResponse(r, err)
  3283  	}
  3284  	defer closeBody(r)
  3285  	return OAuthAppListFromJson(r.Body), BuildResponse(r)
  3286  }
  3287  
  3288  // GetOAuthApp gets a registered OAuth 2.0 client application with Mattermost acting as an OAuth 2.0 service provider.
  3289  func (c *Client4) GetOAuthApp(appId string) (*OAuthApp, *Response) {
  3290  	r, err := c.DoApiGet(c.GetOAuthAppRoute(appId), "")
  3291  	if err != nil {
  3292  		return nil, BuildErrorResponse(r, err)
  3293  	}
  3294  	defer closeBody(r)
  3295  	return OAuthAppFromJson(r.Body), BuildResponse(r)
  3296  }
  3297  
  3298  // GetOAuthAppInfo gets a sanitized version of a registered OAuth 2.0 client application with Mattermost acting as an OAuth 2.0 service provider.
  3299  func (c *Client4) GetOAuthAppInfo(appId string) (*OAuthApp, *Response) {
  3300  	r, err := c.DoApiGet(c.GetOAuthAppRoute(appId)+"/info", "")
  3301  	if err != nil {
  3302  		return nil, BuildErrorResponse(r, err)
  3303  	}
  3304  	defer closeBody(r)
  3305  	return OAuthAppFromJson(r.Body), BuildResponse(r)
  3306  }
  3307  
  3308  // DeleteOAuthApp deletes a registered OAuth 2.0 client application.
  3309  func (c *Client4) DeleteOAuthApp(appId string) (bool, *Response) {
  3310  	r, err := c.DoApiDelete(c.GetOAuthAppRoute(appId))
  3311  	if err != nil {
  3312  		return false, BuildErrorResponse(r, err)
  3313  	}
  3314  	defer closeBody(r)
  3315  	return CheckStatusOK(r), BuildResponse(r)
  3316  }
  3317  
  3318  // RegenerateOAuthAppSecret regenerates the client secret for a registered OAuth 2.0 client application.
  3319  func (c *Client4) RegenerateOAuthAppSecret(appId string) (*OAuthApp, *Response) {
  3320  	r, err := c.DoApiPost(c.GetOAuthAppRoute(appId)+"/regen_secret", "")
  3321  	if err != nil {
  3322  		return nil, BuildErrorResponse(r, err)
  3323  	}
  3324  	defer closeBody(r)
  3325  	return OAuthAppFromJson(r.Body), BuildResponse(r)
  3326  }
  3327  
  3328  // GetAuthorizedOAuthAppsForUser gets a page of OAuth 2.0 client applications the user has authorized to use access their account.
  3329  func (c *Client4) GetAuthorizedOAuthAppsForUser(userId string, page, perPage int) ([]*OAuthApp, *Response) {
  3330  	query := fmt.Sprintf("?page=%v&per_page=%v", page, perPage)
  3331  	r, err := c.DoApiGet(c.GetUserRoute(userId)+"/oauth/apps/authorized"+query, "")
  3332  	if err != nil {
  3333  		return nil, BuildErrorResponse(r, err)
  3334  	}
  3335  	defer closeBody(r)
  3336  	return OAuthAppListFromJson(r.Body), BuildResponse(r)
  3337  }
  3338  
  3339  // AuthorizeOAuthApp will authorize an OAuth 2.0 client application to access a user's account and provide a redirect link to follow.
  3340  func (c *Client4) AuthorizeOAuthApp(authRequest *AuthorizeRequest) (string, *Response) {
  3341  	r, err := c.DoApiRequest(http.MethodPost, c.Url+"/oauth/authorize", authRequest.ToJson(), "")
  3342  	if err != nil {
  3343  		return "", BuildErrorResponse(r, err)
  3344  	}
  3345  	defer closeBody(r)
  3346  	return MapFromJson(r.Body)["redirect"], BuildResponse(r)
  3347  }
  3348  
  3349  // DeauthorizeOAuthApp will deauthorize an OAuth 2.0 client application from accessing a user's account.
  3350  func (c *Client4) DeauthorizeOAuthApp(appId string) (bool, *Response) {
  3351  	requestData := map[string]string{"client_id": appId}
  3352  	r, err := c.DoApiRequest(http.MethodPost, c.Url+"/oauth/deauthorize", MapToJson(requestData), "")
  3353  	if err != nil {
  3354  		return false, BuildErrorResponse(r, err)
  3355  	}
  3356  	defer closeBody(r)
  3357  	return CheckStatusOK(r), BuildResponse(r)
  3358  }
  3359  
  3360  // GetOAuthAccessToken is a test helper function for the OAuth access token endpoint.
  3361  func (c *Client4) GetOAuthAccessToken(data url.Values) (*AccessResponse, *Response) {
  3362  	rq, err := http.NewRequest(http.MethodPost, c.Url+"/oauth/access_token", strings.NewReader(data.Encode()))
  3363  	if err != nil {
  3364  		return nil, &Response{Error: NewAppError(c.Url+"/oauth/access_token", "model.client.connecting.app_error", nil, err.Error(), http.StatusBadRequest)}
  3365  	}
  3366  	rq.Header.Set("Content-Type", "application/x-www-form-urlencoded")
  3367  
  3368  	if len(c.AuthToken) > 0 {
  3369  		rq.Header.Set(HEADER_AUTH, c.AuthType+" "+c.AuthToken)
  3370  	}
  3371  
  3372  	rp, err := c.HttpClient.Do(rq)
  3373  	if err != nil || rp == nil {
  3374  		return nil, &Response{StatusCode: http.StatusForbidden, Error: NewAppError(c.Url+"/oauth/access_token", "model.client.connecting.app_error", nil, err.Error(), 403)}
  3375  	}
  3376  	defer closeBody(rp)
  3377  
  3378  	if rp.StatusCode >= 300 {
  3379  		return nil, BuildErrorResponse(rp, AppErrorFromJson(rp.Body))
  3380  	}
  3381  
  3382  	return AccessResponseFromJson(rp.Body), BuildResponse(rp)
  3383  }
  3384  
  3385  // Elasticsearch Section
  3386  
  3387  // TestElasticsearch will attempt to connect to the configured Elasticsearch server and return OK if configured.
  3388  // correctly.
  3389  func (c *Client4) TestElasticsearch() (bool, *Response) {
  3390  	r, err := c.DoApiPost(c.GetElasticsearchRoute()+"/test", "")
  3391  	if err != nil {
  3392  		return false, BuildErrorResponse(r, err)
  3393  	}
  3394  	defer closeBody(r)
  3395  	return CheckStatusOK(r), BuildResponse(r)
  3396  }
  3397  
  3398  // PurgeElasticsearchIndexes immediately deletes all Elasticsearch indexes.
  3399  func (c *Client4) PurgeElasticsearchIndexes() (bool, *Response) {
  3400  	r, err := c.DoApiPost(c.GetElasticsearchRoute()+"/purge_indexes", "")
  3401  	if err != nil {
  3402  		return false, BuildErrorResponse(r, err)
  3403  	}
  3404  	defer closeBody(r)
  3405  	return CheckStatusOK(r), BuildResponse(r)
  3406  }
  3407  
  3408  // Data Retention Section
  3409  
  3410  // GetDataRetentionPolicy will get the current server data retention policy details.
  3411  func (c *Client4) GetDataRetentionPolicy() (*DataRetentionPolicy, *Response) {
  3412  	r, err := c.DoApiGet(c.GetDataRetentionRoute()+"/policy", "")
  3413  	if err != nil {
  3414  		return nil, BuildErrorResponse(r, err)
  3415  	}
  3416  	defer closeBody(r)
  3417  	return DataRetentionPolicyFromJson(r.Body), BuildResponse(r)
  3418  }
  3419  
  3420  // Commands Section
  3421  
  3422  // CreateCommand will create a new command if the user have the right permissions.
  3423  func (c *Client4) CreateCommand(cmd *Command) (*Command, *Response) {
  3424  	r, err := c.DoApiPost(c.GetCommandsRoute(), cmd.ToJson())
  3425  	if err != nil {
  3426  		return nil, BuildErrorResponse(r, err)
  3427  	}
  3428  	defer closeBody(r)
  3429  	return CommandFromJson(r.Body), BuildResponse(r)
  3430  }
  3431  
  3432  // UpdateCommand updates a command based on the provided Command struct.
  3433  func (c *Client4) UpdateCommand(cmd *Command) (*Command, *Response) {
  3434  	r, err := c.DoApiPut(c.GetCommandRoute(cmd.Id), cmd.ToJson())
  3435  	if err != nil {
  3436  		return nil, BuildErrorResponse(r, err)
  3437  	}
  3438  	defer closeBody(r)
  3439  	return CommandFromJson(r.Body), BuildResponse(r)
  3440  }
  3441  
  3442  // DeleteCommand deletes a command based on the provided command id string.
  3443  func (c *Client4) DeleteCommand(commandId string) (bool, *Response) {
  3444  	r, err := c.DoApiDelete(c.GetCommandRoute(commandId))
  3445  	if err != nil {
  3446  		return false, BuildErrorResponse(r, err)
  3447  	}
  3448  	defer closeBody(r)
  3449  	return CheckStatusOK(r), BuildResponse(r)
  3450  }
  3451  
  3452  // ListCommands will retrieve a list of commands available in the team.
  3453  func (c *Client4) ListCommands(teamId string, customOnly bool) ([]*Command, *Response) {
  3454  	query := fmt.Sprintf("?team_id=%v&custom_only=%v", teamId, customOnly)
  3455  	r, err := c.DoApiGet(c.GetCommandsRoute()+query, "")
  3456  	if err != nil {
  3457  		return nil, BuildErrorResponse(r, err)
  3458  	}
  3459  	defer closeBody(r)
  3460  	return CommandListFromJson(r.Body), BuildResponse(r)
  3461  }
  3462  
  3463  // ExecuteCommand executes a given slash command.
  3464  func (c *Client4) ExecuteCommand(channelId, command string) (*CommandResponse, *Response) {
  3465  	commandArgs := &CommandArgs{
  3466  		ChannelId: channelId,
  3467  		Command:   command,
  3468  	}
  3469  	r, err := c.DoApiPost(c.GetCommandsRoute()+"/execute", commandArgs.ToJson())
  3470  	if err != nil {
  3471  		return nil, BuildErrorResponse(r, err)
  3472  	}
  3473  	defer closeBody(r)
  3474  
  3475  	response, _ := CommandResponseFromJson(r.Body)
  3476  	return response, BuildResponse(r)
  3477  }
  3478  
  3479  // ExecuteCommandWithTeam executes a given slash command against the specified team.
  3480  // Use this when executing slash commands in a DM/GM, since the team id cannot be inferred in that case.
  3481  func (c *Client4) ExecuteCommandWithTeam(channelId, teamId, command string) (*CommandResponse, *Response) {
  3482  	commandArgs := &CommandArgs{
  3483  		ChannelId: channelId,
  3484  		TeamId:    teamId,
  3485  		Command:   command,
  3486  	}
  3487  	r, err := c.DoApiPost(c.GetCommandsRoute()+"/execute", commandArgs.ToJson())
  3488  	if err != nil {
  3489  		return nil, BuildErrorResponse(r, err)
  3490  	}
  3491  	defer closeBody(r)
  3492  
  3493  	response, _ := CommandResponseFromJson(r.Body)
  3494  	return response, BuildResponse(r)
  3495  }
  3496  
  3497  // ListAutocompleteCommands will retrieve a list of commands available in the team.
  3498  func (c *Client4) ListAutocompleteCommands(teamId string) ([]*Command, *Response) {
  3499  	r, err := c.DoApiGet(c.GetTeamAutoCompleteCommandsRoute(teamId), "")
  3500  	if err != nil {
  3501  		return nil, BuildErrorResponse(r, err)
  3502  	}
  3503  	defer closeBody(r)
  3504  	return CommandListFromJson(r.Body), BuildResponse(r)
  3505  }
  3506  
  3507  // RegenCommandToken will create a new token if the user have the right permissions.
  3508  func (c *Client4) RegenCommandToken(commandId string) (string, *Response) {
  3509  	r, err := c.DoApiPut(c.GetCommandRoute(commandId)+"/regen_token", "")
  3510  	if err != nil {
  3511  		return "", BuildErrorResponse(r, err)
  3512  	}
  3513  	defer closeBody(r)
  3514  	return MapFromJson(r.Body)["token"], BuildResponse(r)
  3515  }
  3516  
  3517  // Status Section
  3518  
  3519  // GetUserStatus returns a user based on the provided user id string.
  3520  func (c *Client4) GetUserStatus(userId, etag string) (*Status, *Response) {
  3521  	r, err := c.DoApiGet(c.GetUserStatusRoute(userId), etag)
  3522  	if err != nil {
  3523  		return nil, BuildErrorResponse(r, err)
  3524  	}
  3525  	defer closeBody(r)
  3526  	return StatusFromJson(r.Body), BuildResponse(r)
  3527  }
  3528  
  3529  // GetUsersStatusesByIds returns a list of users status based on the provided user ids.
  3530  func (c *Client4) GetUsersStatusesByIds(userIds []string) ([]*Status, *Response) {
  3531  	r, err := c.DoApiPost(c.GetUserStatusesRoute()+"/ids", ArrayToJson(userIds))
  3532  	if err != nil {
  3533  		return nil, BuildErrorResponse(r, err)
  3534  	}
  3535  	defer closeBody(r)
  3536  	return StatusListFromJson(r.Body), BuildResponse(r)
  3537  }
  3538  
  3539  // UpdateUserStatus sets a user's status based on the provided user id string.
  3540  func (c *Client4) UpdateUserStatus(userId string, userStatus *Status) (*Status, *Response) {
  3541  	r, err := c.DoApiPut(c.GetUserStatusRoute(userId), userStatus.ToJson())
  3542  	if err != nil {
  3543  		return nil, BuildErrorResponse(r, err)
  3544  	}
  3545  	defer closeBody(r)
  3546  	return StatusFromJson(r.Body), BuildResponse(r)
  3547  }
  3548  
  3549  // Emoji Section
  3550  
  3551  // CreateEmoji will save an emoji to the server if the current user has permission
  3552  // to do so. If successful, the provided emoji will be returned with its Id field
  3553  // filled in. Otherwise, an error will be returned.
  3554  func (c *Client4) CreateEmoji(emoji *Emoji, image []byte, filename string) (*Emoji, *Response) {
  3555  	body := &bytes.Buffer{}
  3556  	writer := multipart.NewWriter(body)
  3557  
  3558  	part, err := writer.CreateFormFile("image", filename)
  3559  	if err != nil {
  3560  		return nil, &Response{StatusCode: http.StatusForbidden, Error: NewAppError("CreateEmoji", "model.client.create_emoji.image.app_error", nil, err.Error(), 0)}
  3561  	}
  3562  
  3563  	if _, err := io.Copy(part, bytes.NewBuffer(image)); err != nil {
  3564  		return nil, &Response{StatusCode: http.StatusForbidden, Error: NewAppError("CreateEmoji", "model.client.create_emoji.image.app_error", nil, err.Error(), 0)}
  3565  	}
  3566  
  3567  	if err := writer.WriteField("emoji", emoji.ToJson()); err != nil {
  3568  		return nil, &Response{StatusCode: http.StatusForbidden, Error: NewAppError("CreateEmoji", "model.client.create_emoji.emoji.app_error", nil, err.Error(), 0)}
  3569  	}
  3570  
  3571  	if err := writer.Close(); err != nil {
  3572  		return nil, &Response{StatusCode: http.StatusForbidden, Error: NewAppError("CreateEmoji", "model.client.create_emoji.writer.app_error", nil, err.Error(), 0)}
  3573  	}
  3574  
  3575  	return c.DoEmojiUploadFile(c.GetEmojisRoute(), body.Bytes(), writer.FormDataContentType())
  3576  }
  3577  
  3578  // GetEmojiList returns a page of custom emoji on the system.
  3579  func (c *Client4) GetEmojiList(page, perPage int) ([]*Emoji, *Response) {
  3580  	query := fmt.Sprintf("?page=%v&per_page=%v", page, perPage)
  3581  	r, err := c.DoApiGet(c.GetEmojisRoute()+query, "")
  3582  	if err != nil {
  3583  		return nil, BuildErrorResponse(r, err)
  3584  	}
  3585  	defer closeBody(r)
  3586  	return EmojiListFromJson(r.Body), BuildResponse(r)
  3587  }
  3588  
  3589  // GetSortedEmojiList returns a page of custom emoji on the system sorted based on the sort
  3590  // parameter, blank for no sorting and "name" to sort by emoji names.
  3591  func (c *Client4) GetSortedEmojiList(page, perPage int, sort string) ([]*Emoji, *Response) {
  3592  	query := fmt.Sprintf("?page=%v&per_page=%v&sort=%v", page, perPage, sort)
  3593  	r, err := c.DoApiGet(c.GetEmojisRoute()+query, "")
  3594  	if err != nil {
  3595  		return nil, BuildErrorResponse(r, err)
  3596  	}
  3597  	defer closeBody(r)
  3598  	return EmojiListFromJson(r.Body), BuildResponse(r)
  3599  }
  3600  
  3601  // DeleteEmoji delete an custom emoji on the provided emoji id string.
  3602  func (c *Client4) DeleteEmoji(emojiId string) (bool, *Response) {
  3603  	r, err := c.DoApiDelete(c.GetEmojiRoute(emojiId))
  3604  	if err != nil {
  3605  		return false, BuildErrorResponse(r, err)
  3606  	}
  3607  	defer closeBody(r)
  3608  	return CheckStatusOK(r), BuildResponse(r)
  3609  }
  3610  
  3611  // GetEmoji returns a custom emoji based on the emojiId string.
  3612  func (c *Client4) GetEmoji(emojiId string) (*Emoji, *Response) {
  3613  	r, err := c.DoApiGet(c.GetEmojiRoute(emojiId), "")
  3614  	if err != nil {
  3615  		return nil, BuildErrorResponse(r, err)
  3616  	}
  3617  	defer closeBody(r)
  3618  	return EmojiFromJson(r.Body), BuildResponse(r)
  3619  }
  3620  
  3621  // GetEmojiByName returns a custom emoji based on the name string.
  3622  func (c *Client4) GetEmojiByName(name string) (*Emoji, *Response) {
  3623  	r, err := c.DoApiGet(c.GetEmojiByNameRoute(name), "")
  3624  	if err != nil {
  3625  		return nil, BuildErrorResponse(r, err)
  3626  	}
  3627  	defer closeBody(r)
  3628  	return EmojiFromJson(r.Body), BuildResponse(r)
  3629  }
  3630  
  3631  // GetEmojiImage returns the emoji image.
  3632  func (c *Client4) GetEmojiImage(emojiId string) ([]byte, *Response) {
  3633  	r, apErr := c.DoApiGet(c.GetEmojiRoute(emojiId)+"/image", "")
  3634  	if apErr != nil {
  3635  		return nil, BuildErrorResponse(r, apErr)
  3636  	}
  3637  	defer closeBody(r)
  3638  
  3639  	data, err := ioutil.ReadAll(r.Body)
  3640  	if err != nil {
  3641  		return nil, BuildErrorResponse(r, NewAppError("GetEmojiImage", "model.client.read_file.app_error", nil, err.Error(), r.StatusCode))
  3642  	}
  3643  
  3644  	return data, BuildResponse(r)
  3645  }
  3646  
  3647  // SearchEmoji returns a list of emoji matching some search criteria.
  3648  func (c *Client4) SearchEmoji(search *EmojiSearch) ([]*Emoji, *Response) {
  3649  	r, err := c.DoApiPost(c.GetEmojisRoute()+"/search", search.ToJson())
  3650  	if err != nil {
  3651  		return nil, BuildErrorResponse(r, err)
  3652  	}
  3653  	defer closeBody(r)
  3654  	return EmojiListFromJson(r.Body), BuildResponse(r)
  3655  }
  3656  
  3657  // AutocompleteEmoji returns a list of emoji starting with or matching name.
  3658  func (c *Client4) AutocompleteEmoji(name string, etag string) ([]*Emoji, *Response) {
  3659  	query := fmt.Sprintf("?name=%v", name)
  3660  	r, err := c.DoApiGet(c.GetEmojisRoute()+"/autocomplete"+query, "")
  3661  	if err != nil {
  3662  		return nil, BuildErrorResponse(r, err)
  3663  	}
  3664  	defer closeBody(r)
  3665  	return EmojiListFromJson(r.Body), BuildResponse(r)
  3666  }
  3667  
  3668  // Reaction Section
  3669  
  3670  // SaveReaction saves an emoji reaction for a post. Returns the saved reaction if successful, otherwise an error will be returned.
  3671  func (c *Client4) SaveReaction(reaction *Reaction) (*Reaction, *Response) {
  3672  	r, err := c.DoApiPost(c.GetReactionsRoute(), reaction.ToJson())
  3673  	if err != nil {
  3674  		return nil, BuildErrorResponse(r, err)
  3675  	}
  3676  	defer closeBody(r)
  3677  	return ReactionFromJson(r.Body), BuildResponse(r)
  3678  }
  3679  
  3680  // GetReactions returns a list of reactions to a post.
  3681  func (c *Client4) GetReactions(postId string) ([]*Reaction, *Response) {
  3682  	r, err := c.DoApiGet(c.GetPostRoute(postId)+"/reactions", "")
  3683  	if err != nil {
  3684  		return nil, BuildErrorResponse(r, err)
  3685  	}
  3686  	defer closeBody(r)
  3687  	return ReactionsFromJson(r.Body), BuildResponse(r)
  3688  }
  3689  
  3690  // DeleteReaction deletes reaction of a user in a post.
  3691  func (c *Client4) DeleteReaction(reaction *Reaction) (bool, *Response) {
  3692  	r, err := c.DoApiDelete(c.GetUserRoute(reaction.UserId) + c.GetPostRoute(reaction.PostId) + fmt.Sprintf("/reactions/%v", reaction.EmojiName))
  3693  	if err != nil {
  3694  		return false, BuildErrorResponse(r, err)
  3695  	}
  3696  	defer closeBody(r)
  3697  	return CheckStatusOK(r), BuildResponse(r)
  3698  }
  3699  
  3700  // FetchBulkReactions returns a map of postIds and corresponding reactions
  3701  func (c *Client4) GetBulkReactions(postIds []string) (map[string][]*Reaction, *Response) {
  3702  	r, err := c.DoApiPost(c.GetPostsRoute()+"/ids/reactions", ArrayToJson(postIds))
  3703  	if err != nil {
  3704  		return nil, BuildErrorResponse(r, err)
  3705  	}
  3706  	defer closeBody(r)
  3707  	return MapPostIdToReactionsFromJson(r.Body), BuildResponse(r)
  3708  }
  3709  
  3710  // Timezone Section
  3711  
  3712  // GetSupportedTimezone returns a page of supported timezones on the system.
  3713  func (c *Client4) GetSupportedTimezone() ([]string, *Response) {
  3714  	r, err := c.DoApiGet(c.GetTimezonesRoute(), "")
  3715  	if err != nil {
  3716  		return nil, BuildErrorResponse(r, err)
  3717  	}
  3718  	defer closeBody(r)
  3719  	var timezones []string
  3720  	json.NewDecoder(r.Body).Decode(&timezones)
  3721  	return timezones, BuildResponse(r)
  3722  }
  3723  
  3724  // Open Graph Metadata Section
  3725  
  3726  // OpenGraph return the open graph metadata for a particular url if the site have the metadata.
  3727  func (c *Client4) OpenGraph(url string) (map[string]string, *Response) {
  3728  	requestBody := make(map[string]string)
  3729  	requestBody["url"] = url
  3730  
  3731  	r, err := c.DoApiPost(c.GetOpenGraphRoute(), MapToJson(requestBody))
  3732  	if err != nil {
  3733  		return nil, BuildErrorResponse(r, err)
  3734  	}
  3735  	defer closeBody(r)
  3736  	return MapFromJson(r.Body), BuildResponse(r)
  3737  }
  3738  
  3739  // Jobs Section
  3740  
  3741  // GetJob gets a single job.
  3742  func (c *Client4) GetJob(id string) (*Job, *Response) {
  3743  	r, err := c.DoApiGet(c.GetJobsRoute()+fmt.Sprintf("/%v", id), "")
  3744  	if err != nil {
  3745  		return nil, BuildErrorResponse(r, err)
  3746  	}
  3747  	defer closeBody(r)
  3748  	return JobFromJson(r.Body), BuildResponse(r)
  3749  }
  3750  
  3751  // GetJobs gets all jobs, sorted with the job that was created most recently first.
  3752  func (c *Client4) GetJobs(page int, perPage int) ([]*Job, *Response) {
  3753  	r, err := c.DoApiGet(c.GetJobsRoute()+fmt.Sprintf("?page=%v&per_page=%v", page, perPage), "")
  3754  	if err != nil {
  3755  		return nil, BuildErrorResponse(r, err)
  3756  	}
  3757  	defer closeBody(r)
  3758  	return JobsFromJson(r.Body), BuildResponse(r)
  3759  }
  3760  
  3761  // GetJobsByType gets all jobs of a given type, sorted with the job that was created most recently first.
  3762  func (c *Client4) GetJobsByType(jobType string, page int, perPage int) ([]*Job, *Response) {
  3763  	r, err := c.DoApiGet(c.GetJobsRoute()+fmt.Sprintf("/type/%v?page=%v&per_page=%v", jobType, page, perPage), "")
  3764  	if err != nil {
  3765  		return nil, BuildErrorResponse(r, err)
  3766  	}
  3767  	defer closeBody(r)
  3768  	return JobsFromJson(r.Body), BuildResponse(r)
  3769  }
  3770  
  3771  // CreateJob creates a job based on the provided job struct.
  3772  func (c *Client4) CreateJob(job *Job) (*Job, *Response) {
  3773  	r, err := c.DoApiPost(c.GetJobsRoute(), job.ToJson())
  3774  	if err != nil {
  3775  		return nil, BuildErrorResponse(r, err)
  3776  	}
  3777  	defer closeBody(r)
  3778  	return JobFromJson(r.Body), BuildResponse(r)
  3779  }
  3780  
  3781  // CancelJob requests the cancellation of the job with the provided Id.
  3782  func (c *Client4) CancelJob(jobId string) (bool, *Response) {
  3783  	r, err := c.DoApiPost(c.GetJobsRoute()+fmt.Sprintf("/%v/cancel", jobId), "")
  3784  	if err != nil {
  3785  		return false, BuildErrorResponse(r, err)
  3786  	}
  3787  	defer closeBody(r)
  3788  	return CheckStatusOK(r), BuildResponse(r)
  3789  }
  3790  
  3791  // Roles Section
  3792  
  3793  // GetRole gets a single role by ID.
  3794  func (c *Client4) GetRole(id string) (*Role, *Response) {
  3795  	r, err := c.DoApiGet(c.GetRolesRoute()+fmt.Sprintf("/%v", id), "")
  3796  	if err != nil {
  3797  		return nil, BuildErrorResponse(r, err)
  3798  	}
  3799  	defer closeBody(r)
  3800  	return RoleFromJson(r.Body), BuildResponse(r)
  3801  }
  3802  
  3803  // GetRoleByName gets a single role by Name.
  3804  func (c *Client4) GetRoleByName(name string) (*Role, *Response) {
  3805  	r, err := c.DoApiGet(c.GetRolesRoute()+fmt.Sprintf("/name/%v", name), "")
  3806  	if err != nil {
  3807  		return nil, BuildErrorResponse(r, err)
  3808  	}
  3809  	defer closeBody(r)
  3810  	return RoleFromJson(r.Body), BuildResponse(r)
  3811  }
  3812  
  3813  // GetRolesByNames returns a list of roles based on the provided role names.
  3814  func (c *Client4) GetRolesByNames(roleNames []string) ([]*Role, *Response) {
  3815  	r, err := c.DoApiPost(c.GetRolesRoute()+"/names", ArrayToJson(roleNames))
  3816  	if err != nil {
  3817  		return nil, BuildErrorResponse(r, err)
  3818  	}
  3819  	defer closeBody(r)
  3820  	return RoleListFromJson(r.Body), BuildResponse(r)
  3821  }
  3822  
  3823  // PatchRole partially updates a role in the system. Any missing fields are not updated.
  3824  func (c *Client4) PatchRole(roleId string, patch *RolePatch) (*Role, *Response) {
  3825  	r, err := c.DoApiPut(c.GetRolesRoute()+fmt.Sprintf("/%v/patch", roleId), patch.ToJson())
  3826  	if err != nil {
  3827  		return nil, BuildErrorResponse(r, err)
  3828  	}
  3829  	defer closeBody(r)
  3830  	return RoleFromJson(r.Body), BuildResponse(r)
  3831  }
  3832  
  3833  // Schemes Section
  3834  
  3835  // CreateScheme creates a new Scheme.
  3836  func (c *Client4) CreateScheme(scheme *Scheme) (*Scheme, *Response) {
  3837  	r, err := c.DoApiPost(c.GetSchemesRoute(), scheme.ToJson())
  3838  	if err != nil {
  3839  		return nil, BuildErrorResponse(r, err)
  3840  	}
  3841  	defer closeBody(r)
  3842  	return SchemeFromJson(r.Body), BuildResponse(r)
  3843  }
  3844  
  3845  // GetScheme gets a single scheme by ID.
  3846  func (c *Client4) GetScheme(id string) (*Scheme, *Response) {
  3847  	r, err := c.DoApiGet(c.GetSchemeRoute(id), "")
  3848  	if err != nil {
  3849  		return nil, BuildErrorResponse(r, err)
  3850  	}
  3851  	defer closeBody(r)
  3852  	return SchemeFromJson(r.Body), BuildResponse(r)
  3853  }
  3854  
  3855  // GetSchemes gets all schemes, sorted with the most recently created first, optionally filtered by scope.
  3856  func (c *Client4) GetSchemes(scope string, page int, perPage int) ([]*Scheme, *Response) {
  3857  	r, err := c.DoApiGet(c.GetSchemesRoute()+fmt.Sprintf("?scope=%v&page=%v&per_page=%v", scope, page, perPage), "")
  3858  	if err != nil {
  3859  		return nil, BuildErrorResponse(r, err)
  3860  	}
  3861  	defer closeBody(r)
  3862  	return SchemesFromJson(r.Body), BuildResponse(r)
  3863  }
  3864  
  3865  // DeleteScheme deletes a single scheme by ID.
  3866  func (c *Client4) DeleteScheme(id string) (bool, *Response) {
  3867  	r, err := c.DoApiDelete(c.GetSchemeRoute(id))
  3868  	if err != nil {
  3869  		return false, BuildErrorResponse(r, err)
  3870  	}
  3871  	defer closeBody(r)
  3872  	return CheckStatusOK(r), BuildResponse(r)
  3873  }
  3874  
  3875  // PatchScheme partially updates a scheme in the system. Any missing fields are not updated.
  3876  func (c *Client4) PatchScheme(id string, patch *SchemePatch) (*Scheme, *Response) {
  3877  	r, err := c.DoApiPut(c.GetSchemeRoute(id)+"/patch", patch.ToJson())
  3878  	if err != nil {
  3879  		return nil, BuildErrorResponse(r, err)
  3880  	}
  3881  	defer closeBody(r)
  3882  	return SchemeFromJson(r.Body), BuildResponse(r)
  3883  }
  3884  
  3885  // GetTeamsForScheme gets the teams using this scheme, sorted alphabetically by display name.
  3886  func (c *Client4) GetTeamsForScheme(schemeId string, page int, perPage int) ([]*Team, *Response) {
  3887  	r, err := c.DoApiGet(c.GetSchemeRoute(schemeId)+fmt.Sprintf("/teams?page=%v&per_page=%v", page, perPage), "")
  3888  	if err != nil {
  3889  		return nil, BuildErrorResponse(r, err)
  3890  	}
  3891  	defer closeBody(r)
  3892  	return TeamListFromJson(r.Body), BuildResponse(r)
  3893  }
  3894  
  3895  // GetChannelsForScheme gets the channels using this scheme, sorted alphabetically by display name.
  3896  func (c *Client4) GetChannelsForScheme(schemeId string, page int, perPage int) (ChannelList, *Response) {
  3897  	r, err := c.DoApiGet(c.GetSchemeRoute(schemeId)+fmt.Sprintf("/channels?page=%v&per_page=%v", page, perPage), "")
  3898  	if err != nil {
  3899  		return nil, BuildErrorResponse(r, err)
  3900  	}
  3901  	defer closeBody(r)
  3902  	return *ChannelListFromJson(r.Body), BuildResponse(r)
  3903  }
  3904  
  3905  // Plugin Section
  3906  
  3907  // UploadPlugin takes an io.Reader stream pointing to the contents of a .tar.gz plugin.
  3908  // WARNING: PLUGINS ARE STILL EXPERIMENTAL. THIS FUNCTION IS SUBJECT TO CHANGE.
  3909  func (c *Client4) UploadPlugin(file io.Reader) (*Manifest, *Response) {
  3910  	return c.uploadPlugin(file, false)
  3911  }
  3912  
  3913  func (c *Client4) UploadPluginForced(file io.Reader) (*Manifest, *Response) {
  3914  	return c.uploadPlugin(file, true)
  3915  }
  3916  
  3917  func (c *Client4) uploadPlugin(file io.Reader, force bool) (*Manifest, *Response) {
  3918  	body := new(bytes.Buffer)
  3919  	writer := multipart.NewWriter(body)
  3920  
  3921  	if force {
  3922  		err := writer.WriteField("force", "true")
  3923  		if err != nil {
  3924  			return nil, &Response{Error: NewAppError("UploadPlugin", "model.client.writer.app_error", nil, err.Error(), 0)}
  3925  		}
  3926  	}
  3927  
  3928  	part, err := writer.CreateFormFile("plugin", "plugin.tar.gz")
  3929  	if err != nil {
  3930  		return nil, &Response{Error: NewAppError("UploadPlugin", "model.client.writer.app_error", nil, err.Error(), 0)}
  3931  	}
  3932  
  3933  	if _, err = io.Copy(part, file); err != nil {
  3934  		return nil, &Response{Error: NewAppError("UploadPlugin", "model.client.writer.app_error", nil, err.Error(), 0)}
  3935  	}
  3936  
  3937  	if err = writer.Close(); err != nil {
  3938  		return nil, &Response{Error: NewAppError("UploadPlugin", "model.client.writer.app_error", nil, err.Error(), 0)}
  3939  	}
  3940  
  3941  	rq, err := http.NewRequest("POST", c.ApiUrl+c.GetPluginsRoute(), body)
  3942  	if err != nil {
  3943  		return nil, &Response{Error: NewAppError("UploadPlugin", "model.client.connecting.app_error", nil, err.Error(), http.StatusBadRequest)}
  3944  	}
  3945  	rq.Header.Set("Content-Type", writer.FormDataContentType())
  3946  
  3947  	if len(c.AuthToken) > 0 {
  3948  		rq.Header.Set(HEADER_AUTH, c.AuthType+" "+c.AuthToken)
  3949  	}
  3950  
  3951  	rp, err := c.HttpClient.Do(rq)
  3952  	if err != nil || rp == nil {
  3953  		return nil, BuildErrorResponse(rp, NewAppError("UploadPlugin", "model.client.connecting.app_error", nil, err.Error(), 0))
  3954  	}
  3955  	defer closeBody(rp)
  3956  
  3957  	if rp.StatusCode >= 300 {
  3958  		return nil, BuildErrorResponse(rp, AppErrorFromJson(rp.Body))
  3959  	}
  3960  
  3961  	return ManifestFromJson(rp.Body), BuildResponse(rp)
  3962  }
  3963  
  3964  // GetPlugins will return a list of plugin manifests for currently active plugins.
  3965  // WARNING: PLUGINS ARE STILL EXPERIMENTAL. THIS FUNCTION IS SUBJECT TO CHANGE.
  3966  func (c *Client4) GetPlugins() (*PluginsResponse, *Response) {
  3967  	r, err := c.DoApiGet(c.GetPluginsRoute(), "")
  3968  	if err != nil {
  3969  		return nil, BuildErrorResponse(r, err)
  3970  	}
  3971  	defer closeBody(r)
  3972  	return PluginsResponseFromJson(r.Body), BuildResponse(r)
  3973  }
  3974  
  3975  // GetPluginStatuses will return the plugins installed on any server in the cluster, for reporting
  3976  // to the administrator via the system console.
  3977  // WARNING: PLUGINS ARE STILL EXPERIMENTAL. THIS FUNCTION IS SUBJECT TO CHANGE.
  3978  func (c *Client4) GetPluginStatuses() (PluginStatuses, *Response) {
  3979  	r, err := c.DoApiGet(c.GetPluginsRoute(), "/statuses")
  3980  	if err != nil {
  3981  		return nil, BuildErrorResponse(r, err)
  3982  	}
  3983  	defer closeBody(r)
  3984  	return PluginStatusesFromJson(r.Body), BuildResponse(r)
  3985  }
  3986  
  3987  // RemovePlugin will disable and delete a plugin.
  3988  // WARNING: PLUGINS ARE STILL EXPERIMENTAL. THIS FUNCTION IS SUBJECT TO CHANGE.
  3989  func (c *Client4) RemovePlugin(id string) (bool, *Response) {
  3990  	r, err := c.DoApiDelete(c.GetPluginRoute(id))
  3991  	if err != nil {
  3992  		return false, BuildErrorResponse(r, err)
  3993  	}
  3994  	defer closeBody(r)
  3995  	return CheckStatusOK(r), BuildResponse(r)
  3996  }
  3997  
  3998  // GetWebappPlugins will return a list of plugins that the webapp should download.
  3999  // WARNING: PLUGINS ARE STILL EXPERIMENTAL. THIS FUNCTION IS SUBJECT TO CHANGE.
  4000  func (c *Client4) GetWebappPlugins() ([]*Manifest, *Response) {
  4001  	r, err := c.DoApiGet(c.GetPluginsRoute()+"/webapp", "")
  4002  	if err != nil {
  4003  		return nil, BuildErrorResponse(r, err)
  4004  	}
  4005  	defer closeBody(r)
  4006  	return ManifestListFromJson(r.Body), BuildResponse(r)
  4007  }
  4008  
  4009  // EnablePlugin will enable an plugin installed.
  4010  // WARNING: PLUGINS ARE STILL EXPERIMENTAL. THIS FUNCTION IS SUBJECT TO CHANGE.
  4011  func (c *Client4) EnablePlugin(id string) (bool, *Response) {
  4012  	r, err := c.DoApiPost(c.GetPluginRoute(id)+"/enable", "")
  4013  	if err != nil {
  4014  		return false, BuildErrorResponse(r, err)
  4015  	}
  4016  	defer closeBody(r)
  4017  	return CheckStatusOK(r), BuildResponse(r)
  4018  }
  4019  
  4020  // DisablePlugin will disable an enabled plugin.
  4021  // WARNING: PLUGINS ARE STILL EXPERIMENTAL. THIS FUNCTION IS SUBJECT TO CHANGE.
  4022  func (c *Client4) DisablePlugin(id string) (bool, *Response) {
  4023  	r, err := c.DoApiPost(c.GetPluginRoute(id)+"/disable", "")
  4024  	if err != nil {
  4025  		return false, BuildErrorResponse(r, err)
  4026  	}
  4027  	defer closeBody(r)
  4028  	return CheckStatusOK(r), BuildResponse(r)
  4029  }
  4030  
  4031  // UpdateChannelScheme will update a channel's scheme.
  4032  func (c *Client4) UpdateChannelScheme(channelId, schemeId string) (bool, *Response) {
  4033  	sip := &SchemeIDPatch{SchemeID: &schemeId}
  4034  	r, err := c.DoApiPut(c.GetChannelSchemeRoute(channelId), sip.ToJson())
  4035  	if err != nil {
  4036  		return false, BuildErrorResponse(r, err)
  4037  	}
  4038  	defer closeBody(r)
  4039  	return CheckStatusOK(r), BuildResponse(r)
  4040  }
  4041  
  4042  // UpdateTeamScheme will update a team's scheme.
  4043  func (c *Client4) UpdateTeamScheme(teamId, schemeId string) (bool, *Response) {
  4044  	sip := &SchemeIDPatch{SchemeID: &schemeId}
  4045  	r, err := c.DoApiPut(c.GetTeamSchemeRoute(teamId), sip.ToJson())
  4046  	if err != nil {
  4047  		return false, BuildErrorResponse(r, err)
  4048  	}
  4049  	defer closeBody(r)
  4050  	return CheckStatusOK(r), BuildResponse(r)
  4051  }
  4052  
  4053  // GetRedirectLocation retrieves the value of the 'Location' header of an HTTP response for a given URL.
  4054  func (c *Client4) GetRedirectLocation(urlParam, etag string) (string, *Response) {
  4055  	url := fmt.Sprintf("%s?url=%s", c.GetRedirectLocationRoute(), url.QueryEscape(urlParam))
  4056  	r, err := c.DoApiGet(url, etag)
  4057  	if err != nil {
  4058  		return "", BuildErrorResponse(r, err)
  4059  	}
  4060  	defer closeBody(r)
  4061  	return MapFromJson(r.Body)["location"], BuildResponse(r)
  4062  }
  4063  
  4064  // RegisterTermsOfServiceAction saves action performed by a user against a specific terms of service.
  4065  func (c *Client4) RegisterTermsOfServiceAction(userId, termsOfServiceId string, accepted bool) (*bool, *Response) {
  4066  	url := c.GetUserTermsOfServiceRoute(userId)
  4067  	data := map[string]interface{}{"termsOfServiceId": termsOfServiceId, "accepted": accepted}
  4068  	r, err := c.DoApiPost(url, StringInterfaceToJson(data))
  4069  	if err != nil {
  4070  		return nil, BuildErrorResponse(r, err)
  4071  	}
  4072  	defer closeBody(r)
  4073  	return NewBool(CheckStatusOK(r)), BuildResponse(r)
  4074  }
  4075  
  4076  // GetTermsOfService fetches the latest terms of service
  4077  func (c *Client4) GetTermsOfService(etag string) (*TermsOfService, *Response) {
  4078  	url := c.GetTermsOfServiceRoute()
  4079  	r, err := c.DoApiGet(url, etag)
  4080  	if err != nil {
  4081  		return nil, BuildErrorResponse(r, err)
  4082  	}
  4083  	defer closeBody(r)
  4084  	return TermsOfServiceFromJson(r.Body), BuildResponse(r)
  4085  }
  4086  
  4087  // GetUserTermsOfService fetches user's latest terms of service action if the latest action was for acceptance.
  4088  func (c *Client4) GetUserTermsOfService(userId, etag string) (*UserTermsOfService, *Response) {
  4089  	url := c.GetUserTermsOfServiceRoute(userId)
  4090  	r, err := c.DoApiGet(url, etag)
  4091  	if err != nil {
  4092  		return nil, BuildErrorResponse(r, err)
  4093  	}
  4094  	defer closeBody(r)
  4095  	return UserTermsOfServiceFromJson(r.Body), BuildResponse(r)
  4096  }
  4097  
  4098  // CreateTermsOfService creates new terms of service.
  4099  func (c *Client4) CreateTermsOfService(text, userId string) (*TermsOfService, *Response) {
  4100  	url := c.GetTermsOfServiceRoute()
  4101  	data := map[string]interface{}{"text": text}
  4102  	r, err := c.DoApiPost(url, StringInterfaceToJson(data))
  4103  	if err != nil {
  4104  		return nil, BuildErrorResponse(r, err)
  4105  	}
  4106  	defer closeBody(r)
  4107  	return TermsOfServiceFromJson(r.Body), BuildResponse(r)
  4108  }
  4109  
  4110  func (c *Client4) GetGroup(groupID, etag string) (*Group, *Response) {
  4111  	r, appErr := c.DoApiGet(c.GetGroupRoute(groupID), etag)
  4112  	if appErr != nil {
  4113  		return nil, BuildErrorResponse(r, appErr)
  4114  	}
  4115  	defer closeBody(r)
  4116  	return GroupFromJson(r.Body), BuildResponse(r)
  4117  }
  4118  
  4119  func (c *Client4) PatchGroup(groupID string, patch *GroupPatch) (*Group, *Response) {
  4120  	payload, _ := json.Marshal(patch)
  4121  	r, appErr := c.DoApiPut(c.GetGroupRoute(groupID)+"/patch", string(payload))
  4122  	if appErr != nil {
  4123  		return nil, BuildErrorResponse(r, appErr)
  4124  	}
  4125  	defer closeBody(r)
  4126  	return GroupFromJson(r.Body), BuildResponse(r)
  4127  }
  4128  
  4129  func (c *Client4) LinkGroupSyncable(groupID, syncableID string, syncableType GroupSyncableType, patch *GroupSyncablePatch) (*GroupSyncable, *Response) {
  4130  	payload, _ := json.Marshal(patch)
  4131  	url := fmt.Sprintf("%s/link", c.GetGroupSyncableRoute(groupID, syncableID, syncableType))
  4132  	r, appErr := c.DoApiPost(url, string(payload))
  4133  	if appErr != nil {
  4134  		return nil, BuildErrorResponse(r, appErr)
  4135  	}
  4136  	defer closeBody(r)
  4137  	return GroupSyncableFromJson(r.Body), BuildResponse(r)
  4138  }
  4139  
  4140  func (c *Client4) UnlinkGroupSyncable(groupID, syncableID string, syncableType GroupSyncableType) *Response {
  4141  	url := fmt.Sprintf("%s/link", c.GetGroupSyncableRoute(groupID, syncableID, syncableType))
  4142  	r, appErr := c.DoApiDelete(url)
  4143  	if appErr != nil {
  4144  		return BuildErrorResponse(r, appErr)
  4145  	}
  4146  	defer closeBody(r)
  4147  	return BuildResponse(r)
  4148  }
  4149  
  4150  func (c *Client4) GetGroupSyncable(groupID, syncableID string, syncableType GroupSyncableType, etag string) (*GroupSyncable, *Response) {
  4151  	r, appErr := c.DoApiGet(c.GetGroupSyncableRoute(groupID, syncableID, syncableType), etag)
  4152  	if appErr != nil {
  4153  		return nil, BuildErrorResponse(r, appErr)
  4154  	}
  4155  	defer closeBody(r)
  4156  	return GroupSyncableFromJson(r.Body), BuildResponse(r)
  4157  }
  4158  
  4159  func (c *Client4) GetGroupSyncables(groupID string, syncableType GroupSyncableType, etag string) ([]*GroupSyncable, *Response) {
  4160  	r, appErr := c.DoApiGet(c.GetGroupSyncablesRoute(groupID, syncableType), etag)
  4161  	if appErr != nil {
  4162  		return nil, BuildErrorResponse(r, appErr)
  4163  	}
  4164  	defer closeBody(r)
  4165  	return GroupSyncablesFromJson(r.Body), BuildResponse(r)
  4166  }
  4167  
  4168  func (c *Client4) PatchGroupSyncable(groupID, syncableID string, syncableType GroupSyncableType, patch *GroupSyncablePatch) (*GroupSyncable, *Response) {
  4169  	payload, _ := json.Marshal(patch)
  4170  	r, appErr := c.DoApiPut(c.GetGroupSyncableRoute(groupID, syncableID, syncableType)+"/patch", string(payload))
  4171  	if appErr != nil {
  4172  		return nil, BuildErrorResponse(r, appErr)
  4173  	}
  4174  	defer closeBody(r)
  4175  	return GroupSyncableFromJson(r.Body), BuildResponse(r)
  4176  }