github.com/mattermosttest/mattermost-server/v5@v5.0.0-20200917143240-9dfa12e121f9/model/client4.go (about)

     1  // Copyright (c) 2015-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"
    14  	"net/http"
    15  	"net/url"
    16  	"strconv"
    17  	"strings"
    18  	"time"
    19  )
    20  
    21  const (
    22  	HEADER_REQUEST_ID         = "X-Request-ID"
    23  	HEADER_VERSION_ID         = "X-Version-ID"
    24  	HEADER_CLUSTER_ID         = "X-Cluster-ID"
    25  	HEADER_ETAG_SERVER        = "ETag"
    26  	HEADER_ETAG_CLIENT        = "If-None-Match"
    27  	HEADER_FORWARDED          = "X-Forwarded-For"
    28  	HEADER_REAL_IP            = "X-Real-IP"
    29  	HEADER_FORWARDED_PROTO    = "X-Forwarded-Proto"
    30  	HEADER_TOKEN              = "token"
    31  	HEADER_CSRF_TOKEN         = "X-CSRF-Token"
    32  	HEADER_BEARER             = "BEARER"
    33  	HEADER_AUTH               = "Authorization"
    34  	HEADER_REQUESTED_WITH     = "X-Requested-With"
    35  	HEADER_REQUESTED_WITH_XML = "XMLHttpRequest"
    36  	STATUS                    = "status"
    37  	STATUS_OK                 = "OK"
    38  	STATUS_FAIL               = "FAIL"
    39  	STATUS_UNHEALTHY          = "UNHEALTHY"
    40  	STATUS_REMOVE             = "REMOVE"
    41  
    42  	CLIENT_DIR = "client"
    43  
    44  	API_URL_SUFFIX_V1 = "/api/v1"
    45  	API_URL_SUFFIX_V4 = "/api/v4"
    46  	API_URL_SUFFIX    = API_URL_SUFFIX_V4
    47  )
    48  
    49  type Response struct {
    50  	StatusCode    int
    51  	Error         *AppError
    52  	RequestId     string
    53  	Etag          string
    54  	ServerVersion string
    55  	Header        http.Header
    56  }
    57  
    58  type Client4 struct {
    59  	Url        string       // The location of the server, for example  "http://localhost:8065"
    60  	ApiUrl     string       // The api location of the server, for example "http://localhost:8065/api/v4"
    61  	HttpClient *http.Client // The http client
    62  	AuthToken  string
    63  	AuthType   string
    64  	HttpHeader map[string]string // Headers to be copied over for each request
    65  
    66  	// TrueString is the string value sent to the server for true boolean query parameters.
    67  	trueString string
    68  
    69  	// FalseString is the string value sent to the server for false boolean query parameters.
    70  	falseString string
    71  }
    72  
    73  // SetBoolString is a helper method for overriding how true and false query string parameters are
    74  // sent to the server.
    75  //
    76  // This method is only exposed for testing. It is never necessary to configure these values
    77  // in production.
    78  func (c *Client4) SetBoolString(value bool, valueStr string) {
    79  	if value {
    80  		c.trueString = valueStr
    81  	} else {
    82  		c.falseString = valueStr
    83  	}
    84  }
    85  
    86  // boolString builds the query string parameter for boolean values.
    87  func (c *Client4) boolString(value bool) string {
    88  	if value && c.trueString != "" {
    89  		return c.trueString
    90  	} else if !value && c.falseString != "" {
    91  		return c.falseString
    92  	}
    93  
    94  	if value {
    95  		return "true"
    96  	} else {
    97  		return "false"
    98  	}
    99  }
   100  
   101  func closeBody(r *http.Response) {
   102  	if r.Body != nil {
   103  		_, _ = io.Copy(ioutil.Discard, r.Body)
   104  		_ = r.Body.Close()
   105  	}
   106  }
   107  
   108  // Must is a convenience function used for testing.
   109  func (c *Client4) Must(result interface{}, resp *Response) interface{} {
   110  	if resp.Error != nil {
   111  		time.Sleep(time.Second)
   112  		panic(resp.Error)
   113  	}
   114  
   115  	return result
   116  }
   117  
   118  func NewAPIv4Client(url string) *Client4 {
   119  	return &Client4{url, url + API_URL_SUFFIX, &http.Client{}, "", "", map[string]string{}, "", ""}
   120  }
   121  
   122  func NewAPIv4SocketClient(socketPath string) *Client4 {
   123  	tr := &http.Transport{
   124  		Dial: func(network, addr string) (net.Conn, error) {
   125  			return net.Dial("unix", socketPath)
   126  		},
   127  	}
   128  
   129  	client := NewAPIv4Client("http://_")
   130  	client.HttpClient = &http.Client{Transport: tr}
   131  
   132  	return client
   133  }
   134  
   135  func BuildErrorResponse(r *http.Response, err *AppError) *Response {
   136  	var statusCode int
   137  	var header http.Header
   138  	if r != nil {
   139  		statusCode = r.StatusCode
   140  		header = r.Header
   141  	} else {
   142  		statusCode = 0
   143  		header = make(http.Header)
   144  	}
   145  
   146  	return &Response{
   147  		StatusCode: statusCode,
   148  		Error:      err,
   149  		Header:     header,
   150  	}
   151  }
   152  
   153  func BuildResponse(r *http.Response) *Response {
   154  	return &Response{
   155  		StatusCode:    r.StatusCode,
   156  		RequestId:     r.Header.Get(HEADER_REQUEST_ID),
   157  		Etag:          r.Header.Get(HEADER_ETAG_SERVER),
   158  		ServerVersion: r.Header.Get(HEADER_VERSION_ID),
   159  		Header:        r.Header,
   160  	}
   161  }
   162  
   163  func (c *Client4) SetToken(token string) {
   164  	c.AuthToken = token
   165  	c.AuthType = HEADER_BEARER
   166  }
   167  
   168  // MockSession is deprecated in favour of SetToken
   169  func (c *Client4) MockSession(token string) {
   170  	c.SetToken(token)
   171  }
   172  
   173  func (c *Client4) SetOAuthToken(token string) {
   174  	c.AuthToken = token
   175  	c.AuthType = HEADER_TOKEN
   176  }
   177  
   178  func (c *Client4) ClearOAuthToken() {
   179  	c.AuthToken = ""
   180  	c.AuthType = HEADER_BEARER
   181  }
   182  
   183  func (c *Client4) GetUsersRoute() string {
   184  	return "/users"
   185  }
   186  
   187  func (c *Client4) GetUserRoute(userId string) string {
   188  	return fmt.Sprintf(c.GetUsersRoute()+"/%v", userId)
   189  }
   190  
   191  func (c *Client4) GetUserCategoryRoute(userID, teamID string) string {
   192  	return c.GetUserRoute(userID) + c.GetTeamRoute(teamID) + "/channels/categories"
   193  }
   194  
   195  func (c *Client4) GetUserAccessTokensRoute() string {
   196  	return fmt.Sprintf(c.GetUsersRoute() + "/tokens")
   197  }
   198  
   199  func (c *Client4) GetUserAccessTokenRoute(tokenId string) string {
   200  	return fmt.Sprintf(c.GetUsersRoute()+"/tokens/%v", tokenId)
   201  }
   202  
   203  func (c *Client4) GetUserByUsernameRoute(userName string) string {
   204  	return fmt.Sprintf(c.GetUsersRoute()+"/username/%v", userName)
   205  }
   206  
   207  func (c *Client4) GetUserByEmailRoute(email string) string {
   208  	return fmt.Sprintf(c.GetUsersRoute()+"/email/%v", email)
   209  }
   210  
   211  func (c *Client4) GetBotsRoute() string {
   212  	return "/bots"
   213  }
   214  
   215  func (c *Client4) GetBotRoute(botUserId string) string {
   216  	return fmt.Sprintf("%s/%s", c.GetBotsRoute(), botUserId)
   217  }
   218  
   219  func (c *Client4) GetTeamsRoute() string {
   220  	return "/teams"
   221  }
   222  
   223  func (c *Client4) GetTeamRoute(teamId string) string {
   224  	return fmt.Sprintf(c.GetTeamsRoute()+"/%v", teamId)
   225  }
   226  
   227  func (c *Client4) GetTeamAutoCompleteCommandsRoute(teamId string) string {
   228  	return fmt.Sprintf(c.GetTeamsRoute()+"/%v/commands/autocomplete", teamId)
   229  }
   230  
   231  func (c *Client4) GetTeamByNameRoute(teamName string) string {
   232  	return fmt.Sprintf(c.GetTeamsRoute()+"/name/%v", teamName)
   233  }
   234  
   235  func (c *Client4) GetTeamMemberRoute(teamId, userId string) string {
   236  	return fmt.Sprintf(c.GetTeamRoute(teamId)+"/members/%v", userId)
   237  }
   238  
   239  func (c *Client4) GetTeamMembersRoute(teamId string) string {
   240  	return fmt.Sprintf(c.GetTeamRoute(teamId) + "/members")
   241  }
   242  
   243  func (c *Client4) GetTeamStatsRoute(teamId string) string {
   244  	return fmt.Sprintf(c.GetTeamRoute(teamId) + "/stats")
   245  }
   246  
   247  func (c *Client4) GetTeamImportRoute(teamId string) string {
   248  	return fmt.Sprintf(c.GetTeamRoute(teamId) + "/import")
   249  }
   250  
   251  func (c *Client4) GetChannelsRoute() string {
   252  	return "/channels"
   253  }
   254  
   255  func (c *Client4) GetChannelsForTeamRoute(teamId string) string {
   256  	return fmt.Sprintf(c.GetTeamRoute(teamId) + "/channels")
   257  }
   258  
   259  func (c *Client4) GetChannelRoute(channelId string) string {
   260  	return fmt.Sprintf(c.GetChannelsRoute()+"/%v", channelId)
   261  }
   262  
   263  func (c *Client4) GetChannelByNameRoute(channelName, teamId string) string {
   264  	return fmt.Sprintf(c.GetTeamRoute(teamId)+"/channels/name/%v", channelName)
   265  }
   266  
   267  func (c *Client4) GetChannelsForTeamForUserRoute(teamId, userId string, includeDeleted bool) string {
   268  	route := fmt.Sprintf(c.GetUserRoute(userId) + c.GetTeamRoute(teamId) + "/channels")
   269  	if includeDeleted {
   270  		query := fmt.Sprintf("?include_deleted=%v", includeDeleted)
   271  		return route + query
   272  	}
   273  	return route
   274  }
   275  
   276  func (c *Client4) GetChannelByNameForTeamNameRoute(channelName, teamName string) string {
   277  	return fmt.Sprintf(c.GetTeamByNameRoute(teamName)+"/channels/name/%v", channelName)
   278  }
   279  
   280  func (c *Client4) GetChannelMembersRoute(channelId string) string {
   281  	return fmt.Sprintf(c.GetChannelRoute(channelId) + "/members")
   282  }
   283  
   284  func (c *Client4) GetChannelMemberRoute(channelId, userId string) string {
   285  	return fmt.Sprintf(c.GetChannelMembersRoute(channelId)+"/%v", userId)
   286  }
   287  
   288  func (c *Client4) GetPostsRoute() string {
   289  	return "/posts"
   290  }
   291  
   292  func (c *Client4) GetPostsEphemeralRoute() string {
   293  	return "/posts/ephemeral"
   294  }
   295  
   296  func (c *Client4) GetConfigRoute() string {
   297  	return "/config"
   298  }
   299  
   300  func (c *Client4) GetLicenseRoute() string {
   301  	return "/license"
   302  }
   303  
   304  func (c *Client4) GetPostRoute(postId string) string {
   305  	return fmt.Sprintf(c.GetPostsRoute()+"/%v", postId)
   306  }
   307  
   308  func (c *Client4) GetFilesRoute() string {
   309  	return "/files"
   310  }
   311  
   312  func (c *Client4) GetFileRoute(fileId string) string {
   313  	return fmt.Sprintf(c.GetFilesRoute()+"/%v", fileId)
   314  }
   315  
   316  func (c *Client4) GetPluginsRoute() string {
   317  	return "/plugins"
   318  }
   319  
   320  func (c *Client4) GetPluginRoute(pluginId string) string {
   321  	return fmt.Sprintf(c.GetPluginsRoute()+"/%v", pluginId)
   322  }
   323  
   324  func (c *Client4) GetSystemRoute() string {
   325  	return "/system"
   326  }
   327  
   328  func (c *Client4) GetTestEmailRoute() string {
   329  	return "/email/test"
   330  }
   331  
   332  func (c *Client4) GetTestSiteURLRoute() string {
   333  	return "/site_url/test"
   334  }
   335  
   336  func (c *Client4) GetTestS3Route() string {
   337  	return "/file/s3_test"
   338  }
   339  
   340  func (c *Client4) GetDatabaseRoute() string {
   341  	return "/database"
   342  }
   343  
   344  func (c *Client4) GetCacheRoute() string {
   345  	return "/caches"
   346  }
   347  
   348  func (c *Client4) GetClusterRoute() string {
   349  	return "/cluster"
   350  }
   351  
   352  func (c *Client4) GetIncomingWebhooksRoute() string {
   353  	return "/hooks/incoming"
   354  }
   355  
   356  func (c *Client4) GetIncomingWebhookRoute(hookID string) string {
   357  	return fmt.Sprintf(c.GetIncomingWebhooksRoute()+"/%v", hookID)
   358  }
   359  
   360  func (c *Client4) GetComplianceReportsRoute() string {
   361  	return "/compliance/reports"
   362  }
   363  
   364  func (c *Client4) GetComplianceReportRoute(reportId string) string {
   365  	return fmt.Sprintf("/compliance/reports/%v", reportId)
   366  }
   367  
   368  func (c *Client4) GetOutgoingWebhooksRoute() string {
   369  	return "/hooks/outgoing"
   370  }
   371  
   372  func (c *Client4) GetOutgoingWebhookRoute(hookID string) string {
   373  	return fmt.Sprintf(c.GetOutgoingWebhooksRoute()+"/%v", hookID)
   374  }
   375  
   376  func (c *Client4) GetPreferencesRoute(userId string) string {
   377  	return fmt.Sprintf(c.GetUserRoute(userId) + "/preferences")
   378  }
   379  
   380  func (c *Client4) GetUserStatusRoute(userId string) string {
   381  	return fmt.Sprintf(c.GetUserRoute(userId) + "/status")
   382  }
   383  
   384  func (c *Client4) GetUserStatusesRoute() string {
   385  	return fmt.Sprintf(c.GetUsersRoute() + "/status")
   386  }
   387  
   388  func (c *Client4) GetSamlRoute() string {
   389  	return "/saml"
   390  }
   391  
   392  func (c *Client4) GetLdapRoute() string {
   393  	return "/ldap"
   394  }
   395  
   396  func (c *Client4) GetBrandRoute() string {
   397  	return "/brand"
   398  }
   399  
   400  func (c *Client4) GetDataRetentionRoute() string {
   401  	return "/data_retention"
   402  }
   403  
   404  func (c *Client4) GetElasticsearchRoute() string {
   405  	return "/elasticsearch"
   406  }
   407  
   408  func (c *Client4) GetBleveRoute() string {
   409  	return "/bleve"
   410  }
   411  
   412  func (c *Client4) GetCommandsRoute() string {
   413  	return "/commands"
   414  }
   415  
   416  func (c *Client4) GetCommandRoute(commandId string) string {
   417  	return fmt.Sprintf(c.GetCommandsRoute()+"/%v", commandId)
   418  }
   419  
   420  func (c *Client4) GetCommandMoveRoute(commandId string) string {
   421  	return fmt.Sprintf(c.GetCommandsRoute()+"/%v/move", commandId)
   422  }
   423  
   424  func (c *Client4) GetEmojisRoute() string {
   425  	return "/emoji"
   426  }
   427  
   428  func (c *Client4) GetEmojiRoute(emojiId string) string {
   429  	return fmt.Sprintf(c.GetEmojisRoute()+"/%v", emojiId)
   430  }
   431  
   432  func (c *Client4) GetEmojiByNameRoute(name string) string {
   433  	return fmt.Sprintf(c.GetEmojisRoute()+"/name/%v", name)
   434  }
   435  
   436  func (c *Client4) GetReactionsRoute() string {
   437  	return "/reactions"
   438  }
   439  
   440  func (c *Client4) GetOAuthAppsRoute() string {
   441  	return "/oauth/apps"
   442  }
   443  
   444  func (c *Client4) GetOAuthAppRoute(appId string) string {
   445  	return fmt.Sprintf("/oauth/apps/%v", appId)
   446  }
   447  
   448  func (c *Client4) GetOpenGraphRoute() string {
   449  	return "/opengraph"
   450  }
   451  
   452  func (c *Client4) GetJobsRoute() string {
   453  	return "/jobs"
   454  }
   455  
   456  func (c *Client4) GetRolesRoute() string {
   457  	return "/roles"
   458  }
   459  
   460  func (c *Client4) GetSchemesRoute() string {
   461  	return "/schemes"
   462  }
   463  
   464  func (c *Client4) GetSchemeRoute(id string) string {
   465  	return c.GetSchemesRoute() + fmt.Sprintf("/%v", id)
   466  }
   467  
   468  func (c *Client4) GetAnalyticsRoute() string {
   469  	return "/analytics"
   470  }
   471  
   472  func (c *Client4) GetTimezonesRoute() string {
   473  	return fmt.Sprintf(c.GetSystemRoute() + "/timezones")
   474  }
   475  
   476  func (c *Client4) GetChannelSchemeRoute(channelId string) string {
   477  	return fmt.Sprintf(c.GetChannelsRoute()+"/%v/scheme", channelId)
   478  }
   479  
   480  func (c *Client4) GetTeamSchemeRoute(teamId string) string {
   481  	return fmt.Sprintf(c.GetTeamsRoute()+"/%v/scheme", teamId)
   482  }
   483  
   484  func (c *Client4) GetTotalUsersStatsRoute() string {
   485  	return fmt.Sprintf(c.GetUsersRoute() + "/stats")
   486  }
   487  
   488  func (c *Client4) GetRedirectLocationRoute() string {
   489  	return "/redirect_location"
   490  }
   491  
   492  func (c *Client4) GetServerBusyRoute() string {
   493  	return "/server_busy"
   494  }
   495  
   496  func (c *Client4) GetUserTermsOfServiceRoute(userId string) string {
   497  	return c.GetUserRoute(userId) + "/terms_of_service"
   498  }
   499  
   500  func (c *Client4) GetTermsOfServiceRoute() string {
   501  	return "/terms_of_service"
   502  }
   503  
   504  func (c *Client4) GetGroupsRoute() string {
   505  	return "/groups"
   506  }
   507  
   508  func (c *Client4) GetPublishUserTypingRoute(userId string) string {
   509  	return c.GetUserRoute(userId) + "/typing"
   510  }
   511  
   512  func (c *Client4) GetGroupRoute(groupID string) string {
   513  	return fmt.Sprintf("%s/%s", c.GetGroupsRoute(), groupID)
   514  }
   515  
   516  func (c *Client4) GetGroupSyncableRoute(groupID, syncableID string, syncableType GroupSyncableType) string {
   517  	return fmt.Sprintf("%s/%ss/%s", c.GetGroupRoute(groupID), strings.ToLower(syncableType.String()), syncableID)
   518  }
   519  
   520  func (c *Client4) GetGroupSyncablesRoute(groupID string, syncableType GroupSyncableType) string {
   521  	return fmt.Sprintf("%s/%ss", c.GetGroupRoute(groupID), strings.ToLower(syncableType.String()))
   522  }
   523  
   524  func (c *Client4) DoApiGet(url string, etag string) (*http.Response, *AppError) {
   525  	return c.DoApiRequest(http.MethodGet, c.ApiUrl+url, "", etag)
   526  }
   527  
   528  func (c *Client4) DoApiPost(url string, data string) (*http.Response, *AppError) {
   529  	return c.DoApiRequest(http.MethodPost, c.ApiUrl+url, data, "")
   530  }
   531  
   532  func (c *Client4) doApiPostBytes(url string, data []byte) (*http.Response, *AppError) {
   533  	return c.doApiRequestBytes(http.MethodPost, c.ApiUrl+url, data, "")
   534  }
   535  
   536  func (c *Client4) DoApiPut(url string, data string) (*http.Response, *AppError) {
   537  	return c.DoApiRequest(http.MethodPut, c.ApiUrl+url, data, "")
   538  }
   539  
   540  func (c *Client4) doApiPutBytes(url string, data []byte) (*http.Response, *AppError) {
   541  	return c.doApiRequestBytes(http.MethodPut, c.ApiUrl+url, data, "")
   542  }
   543  
   544  func (c *Client4) DoApiDelete(url string) (*http.Response, *AppError) {
   545  	return c.DoApiRequest(http.MethodDelete, c.ApiUrl+url, "", "")
   546  }
   547  
   548  func (c *Client4) DoApiRequest(method, url, data, etag string) (*http.Response, *AppError) {
   549  	return c.doApiRequestReader(method, url, strings.NewReader(data), etag)
   550  }
   551  
   552  func (c *Client4) doApiRequestBytes(method, url string, data []byte, etag string) (*http.Response, *AppError) {
   553  	return c.doApiRequestReader(method, url, bytes.NewReader(data), etag)
   554  }
   555  
   556  func (c *Client4) doApiRequestReader(method, url string, data io.Reader, etag string) (*http.Response, *AppError) {
   557  	rq, err := http.NewRequest(method, url, data)
   558  	if err != nil {
   559  		return nil, NewAppError(url, "model.client.connecting.app_error", nil, err.Error(), http.StatusBadRequest)
   560  	}
   561  
   562  	if len(etag) > 0 {
   563  		rq.Header.Set(HEADER_ETAG_CLIENT, etag)
   564  	}
   565  
   566  	if len(c.AuthToken) > 0 {
   567  		rq.Header.Set(HEADER_AUTH, c.AuthType+" "+c.AuthToken)
   568  	}
   569  
   570  	if c.HttpHeader != nil && len(c.HttpHeader) > 0 {
   571  		for k, v := range c.HttpHeader {
   572  			rq.Header.Set(k, v)
   573  		}
   574  	}
   575  
   576  	rp, err := c.HttpClient.Do(rq)
   577  	if err != nil || rp == nil {
   578  		return nil, NewAppError(url, "model.client.connecting.app_error", nil, err.Error(), 0)
   579  	}
   580  
   581  	if rp.StatusCode == 304 {
   582  		return rp, nil
   583  	}
   584  
   585  	if rp.StatusCode >= 300 {
   586  		defer closeBody(rp)
   587  		return rp, AppErrorFromJson(rp.Body)
   588  	}
   589  
   590  	return rp, nil
   591  }
   592  
   593  func (c *Client4) DoUploadFile(url string, data []byte, contentType string) (*FileUploadResponse, *Response) {
   594  	return c.doUploadFile(url, bytes.NewReader(data), contentType, 0)
   595  }
   596  
   597  func (c *Client4) doUploadFile(url string, body io.Reader, contentType string, contentLength int64) (*FileUploadResponse, *Response) {
   598  	rq, err := http.NewRequest("POST", c.ApiUrl+url, body)
   599  	if err != nil {
   600  		return nil, &Response{Error: NewAppError(url, "model.client.connecting.app_error", nil, err.Error(), http.StatusBadRequest)}
   601  	}
   602  	if contentLength != 0 {
   603  		rq.ContentLength = contentLength
   604  	}
   605  	rq.Header.Set("Content-Type", contentType)
   606  
   607  	if len(c.AuthToken) > 0 {
   608  		rq.Header.Set(HEADER_AUTH, c.AuthType+" "+c.AuthToken)
   609  	}
   610  
   611  	rp, err := c.HttpClient.Do(rq)
   612  	if err != nil || rp == nil {
   613  		return nil, BuildErrorResponse(rp, NewAppError(url, "model.client.connecting.app_error", nil, err.Error(), 0))
   614  	}
   615  	defer closeBody(rp)
   616  
   617  	if rp.StatusCode >= 300 {
   618  		return nil, BuildErrorResponse(rp, AppErrorFromJson(rp.Body))
   619  	}
   620  
   621  	return FileUploadResponseFromJson(rp.Body), BuildResponse(rp)
   622  }
   623  
   624  func (c *Client4) DoEmojiUploadFile(url string, data []byte, contentType string) (*Emoji, *Response) {
   625  	rq, err := http.NewRequest("POST", c.ApiUrl+url, bytes.NewReader(data))
   626  	if err != nil {
   627  		return nil, &Response{Error: NewAppError(url, "model.client.connecting.app_error", nil, err.Error(), http.StatusBadRequest)}
   628  	}
   629  	rq.Header.Set("Content-Type", contentType)
   630  
   631  	if len(c.AuthToken) > 0 {
   632  		rq.Header.Set(HEADER_AUTH, c.AuthType+" "+c.AuthToken)
   633  	}
   634  
   635  	rp, err := c.HttpClient.Do(rq)
   636  	if err != nil || rp == nil {
   637  		return nil, BuildErrorResponse(rp, NewAppError(url, "model.client.connecting.app_error", nil, err.Error(), 0))
   638  	}
   639  	defer closeBody(rp)
   640  
   641  	if rp.StatusCode >= 300 {
   642  		return nil, BuildErrorResponse(rp, AppErrorFromJson(rp.Body))
   643  	}
   644  
   645  	return EmojiFromJson(rp.Body), BuildResponse(rp)
   646  }
   647  
   648  func (c *Client4) DoUploadImportTeam(url string, data []byte, contentType string) (map[string]string, *Response) {
   649  	rq, err := http.NewRequest("POST", c.ApiUrl+url, bytes.NewReader(data))
   650  	if err != nil {
   651  		return nil, &Response{Error: NewAppError(url, "model.client.connecting.app_error", nil, err.Error(), http.StatusBadRequest)}
   652  	}
   653  	rq.Header.Set("Content-Type", contentType)
   654  
   655  	if len(c.AuthToken) > 0 {
   656  		rq.Header.Set(HEADER_AUTH, c.AuthType+" "+c.AuthToken)
   657  	}
   658  
   659  	rp, err := c.HttpClient.Do(rq)
   660  	if err != nil || rp == nil {
   661  		return nil, BuildErrorResponse(rp, NewAppError(url, "model.client.connecting.app_error", nil, err.Error(), 0))
   662  	}
   663  	defer closeBody(rp)
   664  
   665  	if rp.StatusCode >= 300 {
   666  		return nil, BuildErrorResponse(rp, AppErrorFromJson(rp.Body))
   667  	}
   668  
   669  	return MapFromJson(rp.Body), BuildResponse(rp)
   670  }
   671  
   672  // CheckStatusOK is a convenience function for checking the standard OK response
   673  // from the web service.
   674  func CheckStatusOK(r *http.Response) bool {
   675  	m := MapFromJson(r.Body)
   676  	defer closeBody(r)
   677  
   678  	if m != nil && m[STATUS] == STATUS_OK {
   679  		return true
   680  	}
   681  
   682  	return false
   683  }
   684  
   685  // Authentication Section
   686  
   687  // LoginById authenticates a user by user id and password.
   688  func (c *Client4) LoginById(id string, password string) (*User, *Response) {
   689  	m := make(map[string]string)
   690  	m["id"] = id
   691  	m["password"] = password
   692  	return c.login(m)
   693  }
   694  
   695  // Login authenticates a user by login id, which can be username, email or some sort
   696  // of SSO identifier based on server configuration, and a password.
   697  func (c *Client4) Login(loginId string, password string) (*User, *Response) {
   698  	m := make(map[string]string)
   699  	m["login_id"] = loginId
   700  	m["password"] = password
   701  	return c.login(m)
   702  }
   703  
   704  // LoginByLdap authenticates a user by LDAP id and password.
   705  func (c *Client4) LoginByLdap(loginId string, password string) (*User, *Response) {
   706  	m := make(map[string]string)
   707  	m["login_id"] = loginId
   708  	m["password"] = password
   709  	m["ldap_only"] = c.boolString(true)
   710  	return c.login(m)
   711  }
   712  
   713  // LoginWithDevice authenticates a user by login id (username, email or some sort
   714  // of SSO identifier based on configuration), password and attaches a device id to
   715  // the session.
   716  func (c *Client4) LoginWithDevice(loginId string, password string, deviceId string) (*User, *Response) {
   717  	m := make(map[string]string)
   718  	m["login_id"] = loginId
   719  	m["password"] = password
   720  	m["device_id"] = deviceId
   721  	return c.login(m)
   722  }
   723  
   724  // LoginWithMFA logs a user in with a MFA token
   725  func (c *Client4) LoginWithMFA(loginId, password, mfaToken string) (*User, *Response) {
   726  	m := make(map[string]string)
   727  	m["login_id"] = loginId
   728  	m["password"] = password
   729  	m["token"] = mfaToken
   730  	return c.login(m)
   731  }
   732  
   733  func (c *Client4) login(m map[string]string) (*User, *Response) {
   734  	r, err := c.DoApiPost("/users/login", MapToJson(m))
   735  	if err != nil {
   736  		return nil, BuildErrorResponse(r, err)
   737  	}
   738  	defer closeBody(r)
   739  	c.AuthToken = r.Header.Get(HEADER_TOKEN)
   740  	c.AuthType = HEADER_BEARER
   741  	return UserFromJson(r.Body), BuildResponse(r)
   742  }
   743  
   744  // Logout terminates the current user's session.
   745  func (c *Client4) Logout() (bool, *Response) {
   746  	r, err := c.DoApiPost("/users/logout", "")
   747  	if err != nil {
   748  		return false, BuildErrorResponse(r, err)
   749  	}
   750  	defer closeBody(r)
   751  	c.AuthToken = ""
   752  	c.AuthType = HEADER_BEARER
   753  	return CheckStatusOK(r), BuildResponse(r)
   754  }
   755  
   756  // SwitchAccountType changes a user's login type from one type to another.
   757  func (c *Client4) SwitchAccountType(switchRequest *SwitchRequest) (string, *Response) {
   758  	r, err := c.DoApiPost(c.GetUsersRoute()+"/login/switch", switchRequest.ToJson())
   759  	if err != nil {
   760  		return "", BuildErrorResponse(r, err)
   761  	}
   762  	defer closeBody(r)
   763  	return MapFromJson(r.Body)["follow_link"], BuildResponse(r)
   764  }
   765  
   766  // User Section
   767  
   768  // CreateUser creates a user in the system based on the provided user struct.
   769  func (c *Client4) CreateUser(user *User) (*User, *Response) {
   770  	r, err := c.DoApiPost(c.GetUsersRoute(), user.ToJson())
   771  	if err != nil {
   772  		return nil, BuildErrorResponse(r, err)
   773  	}
   774  	defer closeBody(r)
   775  	return UserFromJson(r.Body), BuildResponse(r)
   776  }
   777  
   778  // CreateUserWithToken creates a user in the system based on the provided tokenId.
   779  func (c *Client4) CreateUserWithToken(user *User, tokenId string) (*User, *Response) {
   780  	if tokenId == "" {
   781  		err := NewAppError("MissingHashOrData", "api.user.create_user.missing_token.app_error", nil, "", http.StatusBadRequest)
   782  		return nil, &Response{StatusCode: err.StatusCode, Error: err}
   783  	}
   784  
   785  	query := fmt.Sprintf("?t=%v", tokenId)
   786  	r, err := c.DoApiPost(c.GetUsersRoute()+query, user.ToJson())
   787  	if err != nil {
   788  		return nil, BuildErrorResponse(r, err)
   789  	}
   790  	defer closeBody(r)
   791  
   792  	return UserFromJson(r.Body), BuildResponse(r)
   793  }
   794  
   795  // CreateUserWithInviteId creates a user in the system based on the provided invited id.
   796  func (c *Client4) CreateUserWithInviteId(user *User, inviteId string) (*User, *Response) {
   797  	if inviteId == "" {
   798  		err := NewAppError("MissingInviteId", "api.user.create_user.missing_invite_id.app_error", nil, "", http.StatusBadRequest)
   799  		return nil, &Response{StatusCode: err.StatusCode, Error: err}
   800  	}
   801  
   802  	query := fmt.Sprintf("?iid=%v", url.QueryEscape(inviteId))
   803  	r, err := c.DoApiPost(c.GetUsersRoute()+query, user.ToJson())
   804  	if err != nil {
   805  		return nil, BuildErrorResponse(r, err)
   806  	}
   807  	defer closeBody(r)
   808  
   809  	return UserFromJson(r.Body), BuildResponse(r)
   810  }
   811  
   812  // GetMe returns the logged in user.
   813  func (c *Client4) GetMe(etag string) (*User, *Response) {
   814  	r, err := c.DoApiGet(c.GetUserRoute(ME), etag)
   815  	if err != nil {
   816  		return nil, BuildErrorResponse(r, err)
   817  	}
   818  	defer closeBody(r)
   819  	return UserFromJson(r.Body), BuildResponse(r)
   820  }
   821  
   822  // GetUser returns a user based on the provided user id string.
   823  func (c *Client4) GetUser(userId, etag string) (*User, *Response) {
   824  	r, err := c.DoApiGet(c.GetUserRoute(userId), etag)
   825  	if err != nil {
   826  		return nil, BuildErrorResponse(r, err)
   827  	}
   828  	defer closeBody(r)
   829  	return UserFromJson(r.Body), BuildResponse(r)
   830  }
   831  
   832  // GetUserByUsername returns a user based on the provided user name string.
   833  func (c *Client4) GetUserByUsername(userName, etag string) (*User, *Response) {
   834  	r, err := c.DoApiGet(c.GetUserByUsernameRoute(userName), etag)
   835  	if err != nil {
   836  		return nil, BuildErrorResponse(r, err)
   837  	}
   838  	defer closeBody(r)
   839  	return UserFromJson(r.Body), BuildResponse(r)
   840  }
   841  
   842  // GetUserByEmail returns a user based on the provided user email string.
   843  func (c *Client4) GetUserByEmail(email, etag string) (*User, *Response) {
   844  	r, err := c.DoApiGet(c.GetUserByEmailRoute(email), etag)
   845  	if err != nil {
   846  		return nil, BuildErrorResponse(r, err)
   847  	}
   848  	defer closeBody(r)
   849  	return UserFromJson(r.Body), BuildResponse(r)
   850  }
   851  
   852  // AutocompleteUsersInTeam returns the users on a team based on search term.
   853  func (c *Client4) AutocompleteUsersInTeam(teamId string, username string, limit int, etag string) (*UserAutocomplete, *Response) {
   854  	query := fmt.Sprintf("?in_team=%v&name=%v&limit=%d", teamId, username, limit)
   855  	r, err := c.DoApiGet(c.GetUsersRoute()+"/autocomplete"+query, etag)
   856  	if err != nil {
   857  		return nil, BuildErrorResponse(r, err)
   858  	}
   859  	defer closeBody(r)
   860  	return UserAutocompleteFromJson(r.Body), BuildResponse(r)
   861  }
   862  
   863  // AutocompleteUsersInChannel returns the users in a channel based on search term.
   864  func (c *Client4) AutocompleteUsersInChannel(teamId string, channelId string, username string, limit int, etag string) (*UserAutocomplete, *Response) {
   865  	query := fmt.Sprintf("?in_team=%v&in_channel=%v&name=%v&limit=%d", teamId, channelId, username, limit)
   866  	r, err := c.DoApiGet(c.GetUsersRoute()+"/autocomplete"+query, etag)
   867  	if err != nil {
   868  		return nil, BuildErrorResponse(r, err)
   869  	}
   870  	defer closeBody(r)
   871  	return UserAutocompleteFromJson(r.Body), BuildResponse(r)
   872  }
   873  
   874  // AutocompleteUsers returns the users in the system based on search term.
   875  func (c *Client4) AutocompleteUsers(username string, limit int, etag string) (*UserAutocomplete, *Response) {
   876  	query := fmt.Sprintf("?name=%v&limit=%d", username, limit)
   877  	r, err := c.DoApiGet(c.GetUsersRoute()+"/autocomplete"+query, etag)
   878  	if err != nil {
   879  		return nil, BuildErrorResponse(r, err)
   880  	}
   881  	defer closeBody(r)
   882  	return UserAutocompleteFromJson(r.Body), BuildResponse(r)
   883  }
   884  
   885  // GetDefaultProfileImage gets the default user's profile image. Must be logged in.
   886  func (c *Client4) GetDefaultProfileImage(userId string) ([]byte, *Response) {
   887  	r, appErr := c.DoApiGet(c.GetUserRoute(userId)+"/image/default", "")
   888  	if appErr != nil {
   889  		return nil, BuildErrorResponse(r, appErr)
   890  	}
   891  	defer closeBody(r)
   892  
   893  	data, err := ioutil.ReadAll(r.Body)
   894  	if err != nil {
   895  		return nil, BuildErrorResponse(r, NewAppError("GetDefaultProfileImage", "model.client.read_file.app_error", nil, err.Error(), r.StatusCode))
   896  	}
   897  
   898  	return data, BuildResponse(r)
   899  }
   900  
   901  // GetProfileImage gets user's profile image. Must be logged in.
   902  func (c *Client4) GetProfileImage(userId, etag string) ([]byte, *Response) {
   903  	r, appErr := c.DoApiGet(c.GetUserRoute(userId)+"/image", etag)
   904  	if appErr != nil {
   905  		return nil, BuildErrorResponse(r, appErr)
   906  	}
   907  	defer closeBody(r)
   908  
   909  	data, err := ioutil.ReadAll(r.Body)
   910  	if err != nil {
   911  		return nil, BuildErrorResponse(r, NewAppError("GetProfileImage", "model.client.read_file.app_error", nil, err.Error(), r.StatusCode))
   912  	}
   913  	return data, BuildResponse(r)
   914  }
   915  
   916  // GetUsers returns a page of users on the system. Page counting starts at 0.
   917  func (c *Client4) GetUsers(page int, perPage int, etag string) ([]*User, *Response) {
   918  	query := fmt.Sprintf("?page=%v&per_page=%v", page, perPage)
   919  	r, err := c.DoApiGet(c.GetUsersRoute()+query, etag)
   920  	if err != nil {
   921  		return nil, BuildErrorResponse(r, err)
   922  	}
   923  	defer closeBody(r)
   924  	return UserListFromJson(r.Body), BuildResponse(r)
   925  }
   926  
   927  // GetUsersInTeam returns a page of users on a team. Page counting starts at 0.
   928  func (c *Client4) GetUsersInTeam(teamId string, page int, perPage int, etag string) ([]*User, *Response) {
   929  	query := fmt.Sprintf("?in_team=%v&page=%v&per_page=%v", teamId, page, perPage)
   930  	r, err := c.DoApiGet(c.GetUsersRoute()+query, etag)
   931  	if err != nil {
   932  		return nil, BuildErrorResponse(r, err)
   933  	}
   934  	defer closeBody(r)
   935  	return UserListFromJson(r.Body), BuildResponse(r)
   936  }
   937  
   938  // GetNewUsersInTeam returns a page of users on a team. Page counting starts at 0.
   939  func (c *Client4) GetNewUsersInTeam(teamId string, page int, perPage int, etag string) ([]*User, *Response) {
   940  	query := fmt.Sprintf("?sort=create_at&in_team=%v&page=%v&per_page=%v", teamId, page, perPage)
   941  	r, err := c.DoApiGet(c.GetUsersRoute()+query, etag)
   942  	if err != nil {
   943  		return nil, BuildErrorResponse(r, err)
   944  	}
   945  	defer closeBody(r)
   946  	return UserListFromJson(r.Body), BuildResponse(r)
   947  }
   948  
   949  // GetRecentlyActiveUsersInTeam returns a page of users on a team. Page counting starts at 0.
   950  func (c *Client4) GetRecentlyActiveUsersInTeam(teamId string, page int, perPage int, etag string) ([]*User, *Response) {
   951  	query := fmt.Sprintf("?sort=last_activity_at&in_team=%v&page=%v&per_page=%v", teamId, page, perPage)
   952  	r, err := c.DoApiGet(c.GetUsersRoute()+query, etag)
   953  	if err != nil {
   954  		return nil, BuildErrorResponse(r, err)
   955  	}
   956  	defer closeBody(r)
   957  	return UserListFromJson(r.Body), BuildResponse(r)
   958  }
   959  
   960  // GetActiveUsersInTeam returns a page of users on a team. Page counting starts at 0.
   961  func (c *Client4) GetActiveUsersInTeam(teamId string, page int, perPage int, etag string) ([]*User, *Response) {
   962  	query := fmt.Sprintf("?active=true&in_team=%v&page=%v&per_page=%v", teamId, page, perPage)
   963  	r, err := c.DoApiGet(c.GetUsersRoute()+query, etag)
   964  	if err != nil {
   965  		return nil, BuildErrorResponse(r, err)
   966  	}
   967  	defer closeBody(r)
   968  	return UserListFromJson(r.Body), BuildResponse(r)
   969  }
   970  
   971  // GetUsersNotInTeam returns a page of users who are not in a team. Page counting starts at 0.
   972  func (c *Client4) GetUsersNotInTeam(teamId string, page int, perPage int, etag string) ([]*User, *Response) {
   973  	query := fmt.Sprintf("?not_in_team=%v&page=%v&per_page=%v", teamId, page, perPage)
   974  	r, err := c.DoApiGet(c.GetUsersRoute()+query, etag)
   975  	if err != nil {
   976  		return nil, BuildErrorResponse(r, err)
   977  	}
   978  	defer closeBody(r)
   979  	return UserListFromJson(r.Body), BuildResponse(r)
   980  }
   981  
   982  // GetUsersInChannel returns a page of users in a channel. Page counting starts at 0.
   983  func (c *Client4) GetUsersInChannel(channelId string, page int, perPage int, etag string) ([]*User, *Response) {
   984  	query := fmt.Sprintf("?in_channel=%v&page=%v&per_page=%v", channelId, page, perPage)
   985  	r, err := c.DoApiGet(c.GetUsersRoute()+query, etag)
   986  	if err != nil {
   987  		return nil, BuildErrorResponse(r, err)
   988  	}
   989  	defer closeBody(r)
   990  	return UserListFromJson(r.Body), BuildResponse(r)
   991  }
   992  
   993  // GetUsersInChannelByStatus returns a page of users in a channel. Page counting starts at 0. Sorted by Status
   994  func (c *Client4) GetUsersInChannelByStatus(channelId string, page int, perPage int, etag string) ([]*User, *Response) {
   995  	query := fmt.Sprintf("?in_channel=%v&page=%v&per_page=%v&sort=status", channelId, page, perPage)
   996  	r, err := c.DoApiGet(c.GetUsersRoute()+query, etag)
   997  	if err != nil {
   998  		return nil, BuildErrorResponse(r, err)
   999  	}
  1000  	defer closeBody(r)
  1001  	return UserListFromJson(r.Body), BuildResponse(r)
  1002  }
  1003  
  1004  // GetUsersNotInChannel returns a page of users not in a channel. Page counting starts at 0.
  1005  func (c *Client4) GetUsersNotInChannel(teamId, channelId string, page int, perPage int, etag string) ([]*User, *Response) {
  1006  	query := fmt.Sprintf("?in_team=%v&not_in_channel=%v&page=%v&per_page=%v", teamId, channelId, page, perPage)
  1007  	r, err := c.DoApiGet(c.GetUsersRoute()+query, etag)
  1008  	if err != nil {
  1009  		return nil, BuildErrorResponse(r, err)
  1010  	}
  1011  	defer closeBody(r)
  1012  	return UserListFromJson(r.Body), BuildResponse(r)
  1013  }
  1014  
  1015  // GetUsersWithoutTeam returns a page of users on the system that aren't on any teams. Page counting starts at 0.
  1016  func (c *Client4) GetUsersWithoutTeam(page int, perPage int, etag string) ([]*User, *Response) {
  1017  	query := fmt.Sprintf("?without_team=1&page=%v&per_page=%v", page, perPage)
  1018  	r, err := c.DoApiGet(c.GetUsersRoute()+query, etag)
  1019  	if err != nil {
  1020  		return nil, BuildErrorResponse(r, err)
  1021  	}
  1022  	defer closeBody(r)
  1023  	return UserListFromJson(r.Body), BuildResponse(r)
  1024  }
  1025  
  1026  // GetUsersInGroup returns a page of users in a group. Page counting starts at 0.
  1027  func (c *Client4) GetUsersInGroup(groupID string, page int, perPage int, etag string) ([]*User, *Response) {
  1028  	query := fmt.Sprintf("?in_group=%v&page=%v&per_page=%v", groupID, page, perPage)
  1029  	r, err := c.DoApiGet(c.GetUsersRoute()+query, etag)
  1030  	if err != nil {
  1031  		return nil, BuildErrorResponse(r, err)
  1032  	}
  1033  	defer closeBody(r)
  1034  	return UserListFromJson(r.Body), BuildResponse(r)
  1035  }
  1036  
  1037  // GetUsersByIds returns a list of users based on the provided user ids.
  1038  func (c *Client4) GetUsersByIds(userIds []string) ([]*User, *Response) {
  1039  	r, err := c.DoApiPost(c.GetUsersRoute()+"/ids", ArrayToJson(userIds))
  1040  	if err != nil {
  1041  		return nil, BuildErrorResponse(r, err)
  1042  	}
  1043  	defer closeBody(r)
  1044  	return UserListFromJson(r.Body), BuildResponse(r)
  1045  }
  1046  
  1047  // GetUsersByIds returns a list of users based on the provided user ids.
  1048  func (c *Client4) GetUsersByIdsWithOptions(userIds []string, options *UserGetByIdsOptions) ([]*User, *Response) {
  1049  	v := url.Values{}
  1050  	if options.Since != 0 {
  1051  		v.Set("since", fmt.Sprintf("%d", options.Since))
  1052  	}
  1053  
  1054  	url := c.GetUsersRoute() + "/ids"
  1055  	if len(v) > 0 {
  1056  		url += "?" + v.Encode()
  1057  	}
  1058  
  1059  	r, err := c.DoApiPost(url, ArrayToJson(userIds))
  1060  	if err != nil {
  1061  		return nil, BuildErrorResponse(r, err)
  1062  	}
  1063  	defer closeBody(r)
  1064  	return UserListFromJson(r.Body), BuildResponse(r)
  1065  }
  1066  
  1067  // GetUsersByUsernames returns a list of users based on the provided usernames.
  1068  func (c *Client4) GetUsersByUsernames(usernames []string) ([]*User, *Response) {
  1069  	r, err := c.DoApiPost(c.GetUsersRoute()+"/usernames", ArrayToJson(usernames))
  1070  	if err != nil {
  1071  		return nil, BuildErrorResponse(r, err)
  1072  	}
  1073  	defer closeBody(r)
  1074  	return UserListFromJson(r.Body), BuildResponse(r)
  1075  }
  1076  
  1077  // GetUsersByGroupChannelIds returns a map with channel ids as keys
  1078  // and a list of users as values based on the provided user ids.
  1079  func (c *Client4) GetUsersByGroupChannelIds(groupChannelIds []string) (map[string][]*User, *Response) {
  1080  	r, err := c.DoApiPost(c.GetUsersRoute()+"/group_channels", ArrayToJson(groupChannelIds))
  1081  	if err != nil {
  1082  		return nil, BuildErrorResponse(r, err)
  1083  	}
  1084  	defer closeBody(r)
  1085  
  1086  	usersByChannelId := map[string][]*User{}
  1087  	json.NewDecoder(r.Body).Decode(&usersByChannelId)
  1088  	return usersByChannelId, BuildResponse(r)
  1089  }
  1090  
  1091  // SearchUsers returns a list of users based on some search criteria.
  1092  func (c *Client4) SearchUsers(search *UserSearch) ([]*User, *Response) {
  1093  	r, err := c.doApiPostBytes(c.GetUsersRoute()+"/search", search.ToJson())
  1094  	if err != nil {
  1095  		return nil, BuildErrorResponse(r, err)
  1096  	}
  1097  	defer closeBody(r)
  1098  	return UserListFromJson(r.Body), BuildResponse(r)
  1099  }
  1100  
  1101  // UpdateUser updates a user in the system based on the provided user struct.
  1102  func (c *Client4) UpdateUser(user *User) (*User, *Response) {
  1103  	r, err := c.DoApiPut(c.GetUserRoute(user.Id), user.ToJson())
  1104  	if err != nil {
  1105  		return nil, BuildErrorResponse(r, err)
  1106  	}
  1107  	defer closeBody(r)
  1108  	return UserFromJson(r.Body), BuildResponse(r)
  1109  }
  1110  
  1111  // PatchUser partially updates a user in the system. Any missing fields are not updated.
  1112  func (c *Client4) PatchUser(userId string, patch *UserPatch) (*User, *Response) {
  1113  	r, err := c.DoApiPut(c.GetUserRoute(userId)+"/patch", patch.ToJson())
  1114  	if err != nil {
  1115  		return nil, BuildErrorResponse(r, err)
  1116  	}
  1117  	defer closeBody(r)
  1118  	return UserFromJson(r.Body), BuildResponse(r)
  1119  }
  1120  
  1121  // UpdateUserAuth updates a user AuthData (uthData, authService and password) in the system.
  1122  func (c *Client4) UpdateUserAuth(userId string, userAuth *UserAuth) (*UserAuth, *Response) {
  1123  	r, err := c.DoApiPut(c.GetUserRoute(userId)+"/auth", userAuth.ToJson())
  1124  	if err != nil {
  1125  		return nil, BuildErrorResponse(r, err)
  1126  	}
  1127  	defer closeBody(r)
  1128  	return UserAuthFromJson(r.Body), BuildResponse(r)
  1129  }
  1130  
  1131  // UpdateUserMfa activates multi-factor authentication for a user if activate
  1132  // is true and a valid code is provided. If activate is false, then code is not
  1133  // required and multi-factor authentication is disabled for the user.
  1134  func (c *Client4) UpdateUserMfa(userId, code string, activate bool) (bool, *Response) {
  1135  	requestBody := make(map[string]interface{})
  1136  	requestBody["activate"] = activate
  1137  	requestBody["code"] = code
  1138  
  1139  	r, err := c.DoApiPut(c.GetUserRoute(userId)+"/mfa", StringInterfaceToJson(requestBody))
  1140  	if err != nil {
  1141  		return false, BuildErrorResponse(r, err)
  1142  	}
  1143  	defer closeBody(r)
  1144  	return CheckStatusOK(r), BuildResponse(r)
  1145  }
  1146  
  1147  // CheckUserMfa checks whether a user has MFA active on their account or not based on the
  1148  // provided login id.
  1149  // Deprecated: Clients should use Login method and check for MFA Error
  1150  func (c *Client4) CheckUserMfa(loginId string) (bool, *Response) {
  1151  	requestBody := make(map[string]interface{})
  1152  	requestBody["login_id"] = loginId
  1153  	r, err := c.DoApiPost(c.GetUsersRoute()+"/mfa", StringInterfaceToJson(requestBody))
  1154  	if err != nil {
  1155  		return false, BuildErrorResponse(r, err)
  1156  	}
  1157  	defer closeBody(r)
  1158  
  1159  	data := StringInterfaceFromJson(r.Body)
  1160  	mfaRequired, ok := data["mfa_required"].(bool)
  1161  	if !ok {
  1162  		return false, BuildResponse(r)
  1163  	}
  1164  	return mfaRequired, BuildResponse(r)
  1165  }
  1166  
  1167  // GenerateMfaSecret will generate a new MFA secret for a user and return it as a string and
  1168  // as a base64 encoded image QR code.
  1169  func (c *Client4) GenerateMfaSecret(userId string) (*MfaSecret, *Response) {
  1170  	r, err := c.DoApiPost(c.GetUserRoute(userId)+"/mfa/generate", "")
  1171  	if err != nil {
  1172  		return nil, BuildErrorResponse(r, err)
  1173  	}
  1174  	defer closeBody(r)
  1175  	return MfaSecretFromJson(r.Body), BuildResponse(r)
  1176  }
  1177  
  1178  // UpdateUserPassword updates a user's password. Must be logged in as the user or be a system administrator.
  1179  func (c *Client4) UpdateUserPassword(userId, currentPassword, newPassword string) (bool, *Response) {
  1180  	requestBody := map[string]string{"current_password": currentPassword, "new_password": newPassword}
  1181  	r, err := c.DoApiPut(c.GetUserRoute(userId)+"/password", MapToJson(requestBody))
  1182  	if err != nil {
  1183  		return false, BuildErrorResponse(r, err)
  1184  	}
  1185  	defer closeBody(r)
  1186  	return CheckStatusOK(r), BuildResponse(r)
  1187  }
  1188  
  1189  // PromoteGuestToUser convert a guest into a regular user
  1190  func (c *Client4) PromoteGuestToUser(guestId string) (bool, *Response) {
  1191  	r, err := c.DoApiPost(c.GetUserRoute(guestId)+"/promote", "")
  1192  	if err != nil {
  1193  		return false, BuildErrorResponse(r, err)
  1194  	}
  1195  	defer closeBody(r)
  1196  	return CheckStatusOK(r), BuildResponse(r)
  1197  }
  1198  
  1199  // DemoteUserToGuest convert a regular user into a guest
  1200  func (c *Client4) DemoteUserToGuest(guestId string) (bool, *Response) {
  1201  	r, err := c.DoApiPost(c.GetUserRoute(guestId)+"/demote", "")
  1202  	if err != nil {
  1203  		return false, BuildErrorResponse(r, err)
  1204  	}
  1205  	defer closeBody(r)
  1206  	return CheckStatusOK(r), BuildResponse(r)
  1207  }
  1208  
  1209  // UpdateUserRoles updates a user's roles in the system. A user can have "system_user" and "system_admin" roles.
  1210  func (c *Client4) UpdateUserRoles(userId, roles string) (bool, *Response) {
  1211  	requestBody := map[string]string{"roles": roles}
  1212  	r, err := c.DoApiPut(c.GetUserRoute(userId)+"/roles", MapToJson(requestBody))
  1213  	if err != nil {
  1214  		return false, BuildErrorResponse(r, err)
  1215  	}
  1216  	defer closeBody(r)
  1217  	return CheckStatusOK(r), BuildResponse(r)
  1218  }
  1219  
  1220  // UpdateUserActive updates status of a user whether active or not.
  1221  func (c *Client4) UpdateUserActive(userId string, active bool) (bool, *Response) {
  1222  	requestBody := make(map[string]interface{})
  1223  	requestBody["active"] = active
  1224  	r, err := c.DoApiPut(c.GetUserRoute(userId)+"/active", StringInterfaceToJson(requestBody))
  1225  	if err != nil {
  1226  		return false, BuildErrorResponse(r, err)
  1227  	}
  1228  	defer closeBody(r)
  1229  
  1230  	return CheckStatusOK(r), BuildResponse(r)
  1231  }
  1232  
  1233  // DeleteUser deactivates a user in the system based on the provided user id string.
  1234  func (c *Client4) DeleteUser(userId string) (bool, *Response) {
  1235  	r, err := c.DoApiDelete(c.GetUserRoute(userId))
  1236  	if err != nil {
  1237  		return false, BuildErrorResponse(r, err)
  1238  	}
  1239  	defer closeBody(r)
  1240  	return CheckStatusOK(r), BuildResponse(r)
  1241  }
  1242  
  1243  // PermanentDeleteUser deletes a user in the system based on the provided user id string.
  1244  func (c *Client4) PermanentDeleteUser(userId string) (bool, *Response) {
  1245  	r, err := c.DoApiDelete(c.GetUserRoute(userId) + "?permanent=" + c.boolString(true))
  1246  	if err != nil {
  1247  		return false, BuildErrorResponse(r, err)
  1248  	}
  1249  	defer closeBody(r)
  1250  	return CheckStatusOK(r), BuildResponse(r)
  1251  }
  1252  
  1253  // ConvertUserToBot converts a user to a bot user.
  1254  func (c *Client4) ConvertUserToBot(userId string) (*Bot, *Response) {
  1255  	r, err := c.DoApiPost(c.GetUserRoute(userId)+"/convert_to_bot", "")
  1256  	if err != nil {
  1257  		return nil, BuildErrorResponse(r, err)
  1258  	}
  1259  	defer closeBody(r)
  1260  	return BotFromJson(r.Body), BuildResponse(r)
  1261  }
  1262  
  1263  // ConvertBotToUser converts a bot user to a user.
  1264  func (c *Client4) ConvertBotToUser(userId string, userPatch *UserPatch, setSystemAdmin bool) (*User, *Response) {
  1265  	var query string
  1266  	if setSystemAdmin {
  1267  		query = "?set_system_admin=true"
  1268  	}
  1269  	r, err := c.DoApiPost(c.GetBotRoute(userId)+"/convert_to_user"+query, userPatch.ToJson())
  1270  	if err != nil {
  1271  		return nil, BuildErrorResponse(r, err)
  1272  	}
  1273  	defer closeBody(r)
  1274  	return UserFromJson(r.Body), BuildResponse(r)
  1275  }
  1276  
  1277  // PermanentDeleteAll permanently deletes all users in the system. This is a local only endpoint
  1278  func (c *Client4) PermanentDeleteAllUsers() (bool, *Response) {
  1279  	r, err := c.DoApiDelete(c.GetUsersRoute())
  1280  	if err != nil {
  1281  		return false, BuildErrorResponse(r, err)
  1282  	}
  1283  	defer closeBody(r)
  1284  	return CheckStatusOK(r), BuildResponse(r)
  1285  }
  1286  
  1287  // SendPasswordResetEmail will send a link for password resetting to a user with the
  1288  // provided email.
  1289  func (c *Client4) SendPasswordResetEmail(email string) (bool, *Response) {
  1290  	requestBody := map[string]string{"email": email}
  1291  	r, err := c.DoApiPost(c.GetUsersRoute()+"/password/reset/send", MapToJson(requestBody))
  1292  	if err != nil {
  1293  		return false, BuildErrorResponse(r, err)
  1294  	}
  1295  	defer closeBody(r)
  1296  	return CheckStatusOK(r), BuildResponse(r)
  1297  }
  1298  
  1299  // ResetPassword uses a recovery code to update reset a user's password.
  1300  func (c *Client4) ResetPassword(token, newPassword string) (bool, *Response) {
  1301  	requestBody := map[string]string{"token": token, "new_password": newPassword}
  1302  	r, err := c.DoApiPost(c.GetUsersRoute()+"/password/reset", MapToJson(requestBody))
  1303  	if err != nil {
  1304  		return false, BuildErrorResponse(r, err)
  1305  	}
  1306  	defer closeBody(r)
  1307  	return CheckStatusOK(r), BuildResponse(r)
  1308  }
  1309  
  1310  // GetSessions returns a list of sessions based on the provided user id string.
  1311  func (c *Client4) GetSessions(userId, etag string) ([]*Session, *Response) {
  1312  	r, err := c.DoApiGet(c.GetUserRoute(userId)+"/sessions", etag)
  1313  	if err != nil {
  1314  		return nil, BuildErrorResponse(r, err)
  1315  	}
  1316  	defer closeBody(r)
  1317  	return SessionsFromJson(r.Body), BuildResponse(r)
  1318  }
  1319  
  1320  // RevokeSession revokes a user session based on the provided user id and session id strings.
  1321  func (c *Client4) RevokeSession(userId, sessionId string) (bool, *Response) {
  1322  	requestBody := map[string]string{"session_id": sessionId}
  1323  	r, err := c.DoApiPost(c.GetUserRoute(userId)+"/sessions/revoke", MapToJson(requestBody))
  1324  	if err != nil {
  1325  		return false, BuildErrorResponse(r, err)
  1326  	}
  1327  	defer closeBody(r)
  1328  	return CheckStatusOK(r), BuildResponse(r)
  1329  }
  1330  
  1331  // RevokeAllSessions revokes all sessions for the provided user id string.
  1332  func (c *Client4) RevokeAllSessions(userId string) (bool, *Response) {
  1333  	r, err := c.DoApiPost(c.GetUserRoute(userId)+"/sessions/revoke/all", "")
  1334  	if err != nil {
  1335  		return false, BuildErrorResponse(r, err)
  1336  	}
  1337  	defer closeBody(r)
  1338  	return CheckStatusOK(r), BuildResponse(r)
  1339  }
  1340  
  1341  // RevokeAllSessions revokes all sessions for all the users.
  1342  func (c *Client4) RevokeSessionsFromAllUsers() (bool, *Response) {
  1343  	r, err := c.DoApiPost(c.GetUsersRoute()+"/sessions/revoke/all", "")
  1344  	if err != nil {
  1345  		return false, BuildErrorResponse(r, err)
  1346  	}
  1347  	defer closeBody(r)
  1348  	return CheckStatusOK(r), BuildResponse(r)
  1349  }
  1350  
  1351  // AttachDeviceId attaches a mobile device ID to the current session.
  1352  func (c *Client4) AttachDeviceId(deviceId string) (bool, *Response) {
  1353  	requestBody := map[string]string{"device_id": deviceId}
  1354  	r, err := c.DoApiPut(c.GetUsersRoute()+"/sessions/device", MapToJson(requestBody))
  1355  	if err != nil {
  1356  		return false, BuildErrorResponse(r, err)
  1357  	}
  1358  	defer closeBody(r)
  1359  	return CheckStatusOK(r), BuildResponse(r)
  1360  }
  1361  
  1362  // GetTeamsUnreadForUser will return an array with TeamUnread objects that contain the amount
  1363  // of unread messages and mentions the current user has for the teams it belongs to.
  1364  // An optional team ID can be set to exclude that team from the results. Must be authenticated.
  1365  func (c *Client4) GetTeamsUnreadForUser(userId, teamIdToExclude string) ([]*TeamUnread, *Response) {
  1366  	var optional string
  1367  	if teamIdToExclude != "" {
  1368  		optional += fmt.Sprintf("?exclude_team=%s", url.QueryEscape(teamIdToExclude))
  1369  	}
  1370  
  1371  	r, err := c.DoApiGet(c.GetUserRoute(userId)+"/teams/unread"+optional, "")
  1372  	if err != nil {
  1373  		return nil, BuildErrorResponse(r, err)
  1374  	}
  1375  	defer closeBody(r)
  1376  	return TeamsUnreadFromJson(r.Body), BuildResponse(r)
  1377  }
  1378  
  1379  // GetUserAudits returns a list of audit based on the provided user id string.
  1380  func (c *Client4) GetUserAudits(userId string, page int, perPage int, etag string) (Audits, *Response) {
  1381  	query := fmt.Sprintf("?page=%v&per_page=%v", page, perPage)
  1382  	r, err := c.DoApiGet(c.GetUserRoute(userId)+"/audits"+query, etag)
  1383  	if err != nil {
  1384  		return nil, BuildErrorResponse(r, err)
  1385  	}
  1386  	defer closeBody(r)
  1387  	return AuditsFromJson(r.Body), BuildResponse(r)
  1388  }
  1389  
  1390  // VerifyUserEmail will verify a user's email using the supplied token.
  1391  func (c *Client4) VerifyUserEmail(token string) (bool, *Response) {
  1392  	requestBody := map[string]string{"token": token}
  1393  	r, err := c.DoApiPost(c.GetUsersRoute()+"/email/verify", MapToJson(requestBody))
  1394  	if err != nil {
  1395  		return false, BuildErrorResponse(r, err)
  1396  	}
  1397  	defer closeBody(r)
  1398  	return CheckStatusOK(r), BuildResponse(r)
  1399  }
  1400  
  1401  // VerifyUserEmailWithoutToken will verify a user's email by its Id. (Requires manage system role)
  1402  func (c *Client4) VerifyUserEmailWithoutToken(userId string) (*User, *Response) {
  1403  	r, err := c.DoApiPost(c.GetUserRoute(userId)+"/email/verify/member", "")
  1404  	if err != nil {
  1405  		return nil, BuildErrorResponse(r, err)
  1406  	}
  1407  	defer closeBody(r)
  1408  	return UserFromJson(r.Body), BuildResponse(r)
  1409  }
  1410  
  1411  // SendVerificationEmail will send an email to the user with the provided email address, if
  1412  // that user exists. The email will contain a link that can be used to verify the user's
  1413  // email address.
  1414  func (c *Client4) SendVerificationEmail(email string) (bool, *Response) {
  1415  	requestBody := map[string]string{"email": email}
  1416  	r, err := c.DoApiPost(c.GetUsersRoute()+"/email/verify/send", MapToJson(requestBody))
  1417  	if err != nil {
  1418  		return false, BuildErrorResponse(r, err)
  1419  	}
  1420  	defer closeBody(r)
  1421  	return CheckStatusOK(r), BuildResponse(r)
  1422  }
  1423  
  1424  // SetDefaultProfileImage resets the profile image to a default generated one.
  1425  func (c *Client4) SetDefaultProfileImage(userId string) (bool, *Response) {
  1426  	r, err := c.DoApiDelete(c.GetUserRoute(userId) + "/image")
  1427  	if err != nil {
  1428  		return false, BuildErrorResponse(r, err)
  1429  	}
  1430  	return CheckStatusOK(r), BuildResponse(r)
  1431  }
  1432  
  1433  // SetProfileImage sets profile image of the user.
  1434  func (c *Client4) SetProfileImage(userId string, data []byte) (bool, *Response) {
  1435  	body := &bytes.Buffer{}
  1436  	writer := multipart.NewWriter(body)
  1437  
  1438  	part, err := writer.CreateFormFile("image", "profile.png")
  1439  	if err != nil {
  1440  		return false, &Response{Error: NewAppError("SetProfileImage", "model.client.set_profile_user.no_file.app_error", nil, err.Error(), http.StatusBadRequest)}
  1441  	}
  1442  
  1443  	if _, err = io.Copy(part, bytes.NewBuffer(data)); err != nil {
  1444  		return false, &Response{Error: NewAppError("SetProfileImage", "model.client.set_profile_user.no_file.app_error", nil, err.Error(), http.StatusBadRequest)}
  1445  	}
  1446  
  1447  	if err = writer.Close(); err != nil {
  1448  		return false, &Response{Error: NewAppError("SetProfileImage", "model.client.set_profile_user.writer.app_error", nil, err.Error(), http.StatusBadRequest)}
  1449  	}
  1450  
  1451  	rq, err := http.NewRequest("POST", c.ApiUrl+c.GetUserRoute(userId)+"/image", bytes.NewReader(body.Bytes()))
  1452  	if err != nil {
  1453  		return false, &Response{Error: NewAppError("SetProfileImage", "model.client.connecting.app_error", nil, err.Error(), http.StatusBadRequest)}
  1454  	}
  1455  	rq.Header.Set("Content-Type", writer.FormDataContentType())
  1456  
  1457  	if len(c.AuthToken) > 0 {
  1458  		rq.Header.Set(HEADER_AUTH, c.AuthType+" "+c.AuthToken)
  1459  	}
  1460  
  1461  	rp, err := c.HttpClient.Do(rq)
  1462  	if err != nil || rp == nil {
  1463  		return false, &Response{StatusCode: http.StatusForbidden, Error: NewAppError(c.GetUserRoute(userId)+"/image", "model.client.connecting.app_error", nil, err.Error(), http.StatusForbidden)}
  1464  	}
  1465  	defer closeBody(rp)
  1466  
  1467  	if rp.StatusCode >= 300 {
  1468  		return false, BuildErrorResponse(rp, AppErrorFromJson(rp.Body))
  1469  	}
  1470  
  1471  	return CheckStatusOK(rp), BuildResponse(rp)
  1472  }
  1473  
  1474  // CreateUserAccessToken will generate a user access token that can be used in place
  1475  // of a session token to access the REST API. Must have the 'create_user_access_token'
  1476  // permission and if generating for another user, must have the 'edit_other_users'
  1477  // permission. A non-blank description is required.
  1478  func (c *Client4) CreateUserAccessToken(userId, description string) (*UserAccessToken, *Response) {
  1479  	requestBody := map[string]string{"description": description}
  1480  	r, err := c.DoApiPost(c.GetUserRoute(userId)+"/tokens", MapToJson(requestBody))
  1481  	if err != nil {
  1482  		return nil, BuildErrorResponse(r, err)
  1483  	}
  1484  	defer closeBody(r)
  1485  	return UserAccessTokenFromJson(r.Body), BuildResponse(r)
  1486  }
  1487  
  1488  // GetUserAccessTokens will get a page of access tokens' id, description, is_active
  1489  // and the user_id in the system. The actual token will not be returned. Must have
  1490  // the 'manage_system' permission.
  1491  func (c *Client4) GetUserAccessTokens(page int, perPage int) ([]*UserAccessToken, *Response) {
  1492  	query := fmt.Sprintf("?page=%v&per_page=%v", page, perPage)
  1493  	r, err := c.DoApiGet(c.GetUserAccessTokensRoute()+query, "")
  1494  	if err != nil {
  1495  		return nil, BuildErrorResponse(r, err)
  1496  	}
  1497  	defer closeBody(r)
  1498  	return UserAccessTokenListFromJson(r.Body), BuildResponse(r)
  1499  }
  1500  
  1501  // GetUserAccessToken will get a user access tokens' id, description, is_active
  1502  // and the user_id of the user it is for. The actual token will not be returned.
  1503  // Must have the 'read_user_access_token' permission and if getting for another
  1504  // user, must have the 'edit_other_users' permission.
  1505  func (c *Client4) GetUserAccessToken(tokenId string) (*UserAccessToken, *Response) {
  1506  	r, err := c.DoApiGet(c.GetUserAccessTokenRoute(tokenId), "")
  1507  	if err != nil {
  1508  		return nil, BuildErrorResponse(r, err)
  1509  	}
  1510  	defer closeBody(r)
  1511  	return UserAccessTokenFromJson(r.Body), BuildResponse(r)
  1512  }
  1513  
  1514  // GetUserAccessTokensForUser will get a paged list of user access tokens showing id,
  1515  // description and user_id for each. The actual tokens will not be returned. Must have
  1516  // the 'read_user_access_token' permission and if getting for another user, must have the
  1517  // 'edit_other_users' permission.
  1518  func (c *Client4) GetUserAccessTokensForUser(userId string, page, perPage int) ([]*UserAccessToken, *Response) {
  1519  	query := fmt.Sprintf("?page=%v&per_page=%v", page, perPage)
  1520  	r, err := c.DoApiGet(c.GetUserRoute(userId)+"/tokens"+query, "")
  1521  	if err != nil {
  1522  		return nil, BuildErrorResponse(r, err)
  1523  	}
  1524  	defer closeBody(r)
  1525  	return UserAccessTokenListFromJson(r.Body), BuildResponse(r)
  1526  }
  1527  
  1528  // RevokeUserAccessToken will revoke a user access token by id. Must have the
  1529  // 'revoke_user_access_token' permission and if revoking for another user, must have the
  1530  // 'edit_other_users' permission.
  1531  func (c *Client4) RevokeUserAccessToken(tokenId string) (bool, *Response) {
  1532  	requestBody := map[string]string{"token_id": tokenId}
  1533  	r, err := c.DoApiPost(c.GetUsersRoute()+"/tokens/revoke", MapToJson(requestBody))
  1534  	if err != nil {
  1535  		return false, BuildErrorResponse(r, err)
  1536  	}
  1537  	defer closeBody(r)
  1538  	return CheckStatusOK(r), BuildResponse(r)
  1539  }
  1540  
  1541  // SearchUserAccessTokens returns user access tokens matching the provided search term.
  1542  func (c *Client4) SearchUserAccessTokens(search *UserAccessTokenSearch) ([]*UserAccessToken, *Response) {
  1543  	r, err := c.DoApiPost(c.GetUsersRoute()+"/tokens/search", search.ToJson())
  1544  	if err != nil {
  1545  		return nil, BuildErrorResponse(r, err)
  1546  	}
  1547  	defer closeBody(r)
  1548  	return UserAccessTokenListFromJson(r.Body), BuildResponse(r)
  1549  }
  1550  
  1551  // DisableUserAccessToken will disable a user access token by id. Must have the
  1552  // 'revoke_user_access_token' permission and if disabling for another user, must have the
  1553  // 'edit_other_users' permission.
  1554  func (c *Client4) DisableUserAccessToken(tokenId string) (bool, *Response) {
  1555  	requestBody := map[string]string{"token_id": tokenId}
  1556  	r, err := c.DoApiPost(c.GetUsersRoute()+"/tokens/disable", MapToJson(requestBody))
  1557  	if err != nil {
  1558  		return false, BuildErrorResponse(r, err)
  1559  	}
  1560  	defer closeBody(r)
  1561  	return CheckStatusOK(r), BuildResponse(r)
  1562  }
  1563  
  1564  // EnableUserAccessToken will enable a user access token by id. Must have the
  1565  // 'create_user_access_token' permission and if enabling for another user, must have the
  1566  // 'edit_other_users' permission.
  1567  func (c *Client4) EnableUserAccessToken(tokenId string) (bool, *Response) {
  1568  	requestBody := map[string]string{"token_id": tokenId}
  1569  	r, err := c.DoApiPost(c.GetUsersRoute()+"/tokens/enable", MapToJson(requestBody))
  1570  	if err != nil {
  1571  		return false, BuildErrorResponse(r, err)
  1572  	}
  1573  	defer closeBody(r)
  1574  	return CheckStatusOK(r), BuildResponse(r)
  1575  }
  1576  
  1577  // Bots section
  1578  
  1579  // CreateBot creates a bot in the system based on the provided bot struct.
  1580  func (c *Client4) CreateBot(bot *Bot) (*Bot, *Response) {
  1581  	r, err := c.doApiPostBytes(c.GetBotsRoute(), bot.ToJson())
  1582  	if err != nil {
  1583  		return nil, BuildErrorResponse(r, err)
  1584  	}
  1585  	defer closeBody(r)
  1586  	return BotFromJson(r.Body), BuildResponse(r)
  1587  }
  1588  
  1589  // PatchBot partially updates a bot. Any missing fields are not updated.
  1590  func (c *Client4) PatchBot(userId string, patch *BotPatch) (*Bot, *Response) {
  1591  	r, err := c.doApiPutBytes(c.GetBotRoute(userId), patch.ToJson())
  1592  	if err != nil {
  1593  		return nil, BuildErrorResponse(r, err)
  1594  	}
  1595  	defer closeBody(r)
  1596  	return BotFromJson(r.Body), BuildResponse(r)
  1597  }
  1598  
  1599  // GetBot fetches the given, undeleted bot.
  1600  func (c *Client4) GetBot(userId string, etag string) (*Bot, *Response) {
  1601  	r, err := c.DoApiGet(c.GetBotRoute(userId), etag)
  1602  	if err != nil {
  1603  		return nil, BuildErrorResponse(r, err)
  1604  	}
  1605  	defer closeBody(r)
  1606  	return BotFromJson(r.Body), BuildResponse(r)
  1607  }
  1608  
  1609  // GetBot fetches the given bot, even if it is deleted.
  1610  func (c *Client4) GetBotIncludeDeleted(userId string, etag string) (*Bot, *Response) {
  1611  	r, err := c.DoApiGet(c.GetBotRoute(userId)+"?include_deleted="+c.boolString(true), etag)
  1612  	if err != nil {
  1613  		return nil, BuildErrorResponse(r, err)
  1614  	}
  1615  	defer closeBody(r)
  1616  	return BotFromJson(r.Body), BuildResponse(r)
  1617  }
  1618  
  1619  // GetBots fetches the given page of bots, excluding deleted.
  1620  func (c *Client4) GetBots(page, perPage int, etag string) ([]*Bot, *Response) {
  1621  	query := fmt.Sprintf("?page=%v&per_page=%v", page, perPage)
  1622  	r, err := c.DoApiGet(c.GetBotsRoute()+query, etag)
  1623  	if err != nil {
  1624  		return nil, BuildErrorResponse(r, err)
  1625  	}
  1626  	defer closeBody(r)
  1627  	return BotListFromJson(r.Body), BuildResponse(r)
  1628  }
  1629  
  1630  // GetBotsIncludeDeleted fetches the given page of bots, including deleted.
  1631  func (c *Client4) GetBotsIncludeDeleted(page, perPage int, etag string) ([]*Bot, *Response) {
  1632  	query := fmt.Sprintf("?page=%v&per_page=%v&include_deleted="+c.boolString(true), page, perPage)
  1633  	r, err := c.DoApiGet(c.GetBotsRoute()+query, etag)
  1634  	if err != nil {
  1635  		return nil, BuildErrorResponse(r, err)
  1636  	}
  1637  	defer closeBody(r)
  1638  	return BotListFromJson(r.Body), BuildResponse(r)
  1639  }
  1640  
  1641  // GetBotsOrphaned fetches the given page of bots, only including orphanded bots.
  1642  func (c *Client4) GetBotsOrphaned(page, perPage int, etag string) ([]*Bot, *Response) {
  1643  	query := fmt.Sprintf("?page=%v&per_page=%v&only_orphaned="+c.boolString(true), page, perPage)
  1644  	r, err := c.DoApiGet(c.GetBotsRoute()+query, etag)
  1645  	if err != nil {
  1646  		return nil, BuildErrorResponse(r, err)
  1647  	}
  1648  	defer closeBody(r)
  1649  	return BotListFromJson(r.Body), BuildResponse(r)
  1650  }
  1651  
  1652  // DisableBot disables the given bot in the system.
  1653  func (c *Client4) DisableBot(botUserId string) (*Bot, *Response) {
  1654  	r, err := c.doApiPostBytes(c.GetBotRoute(botUserId)+"/disable", nil)
  1655  	if err != nil {
  1656  		return nil, BuildErrorResponse(r, err)
  1657  	}
  1658  	defer closeBody(r)
  1659  	return BotFromJson(r.Body), BuildResponse(r)
  1660  }
  1661  
  1662  // EnableBot disables the given bot in the system.
  1663  func (c *Client4) EnableBot(botUserId string) (*Bot, *Response) {
  1664  	r, err := c.doApiPostBytes(c.GetBotRoute(botUserId)+"/enable", nil)
  1665  	if err != nil {
  1666  		return nil, BuildErrorResponse(r, err)
  1667  	}
  1668  	defer closeBody(r)
  1669  	return BotFromJson(r.Body), BuildResponse(r)
  1670  }
  1671  
  1672  // AssignBot assigns the given bot to the given user
  1673  func (c *Client4) AssignBot(botUserId, newOwnerId string) (*Bot, *Response) {
  1674  	r, err := c.doApiPostBytes(c.GetBotRoute(botUserId)+"/assign/"+newOwnerId, nil)
  1675  	if err != nil {
  1676  		return nil, BuildErrorResponse(r, err)
  1677  	}
  1678  	defer closeBody(r)
  1679  	return BotFromJson(r.Body), BuildResponse(r)
  1680  }
  1681  
  1682  // SetBotIconImage sets LHS bot icon image.
  1683  func (c *Client4) SetBotIconImage(botUserId string, data []byte) (bool, *Response) {
  1684  	body := &bytes.Buffer{}
  1685  	writer := multipart.NewWriter(body)
  1686  
  1687  	part, err := writer.CreateFormFile("image", "icon.svg")
  1688  	if err != nil {
  1689  		return false, &Response{Error: NewAppError("SetBotIconImage", "model.client.set_bot_icon_image.no_file.app_error", nil, err.Error(), http.StatusBadRequest)}
  1690  	}
  1691  
  1692  	if _, err = io.Copy(part, bytes.NewBuffer(data)); err != nil {
  1693  		return false, &Response{Error: NewAppError("SetBotIconImage", "model.client.set_bot_icon_image.no_file.app_error", nil, err.Error(), http.StatusBadRequest)}
  1694  	}
  1695  
  1696  	if err = writer.Close(); err != nil {
  1697  		return false, &Response{Error: NewAppError("SetBotIconImage", "model.client.set_bot_icon_image.writer.app_error", nil, err.Error(), http.StatusBadRequest)}
  1698  	}
  1699  
  1700  	rq, err := http.NewRequest("POST", c.ApiUrl+c.GetBotRoute(botUserId)+"/icon", bytes.NewReader(body.Bytes()))
  1701  	if err != nil {
  1702  		return false, &Response{Error: NewAppError("SetBotIconImage", "model.client.connecting.app_error", nil, err.Error(), http.StatusBadRequest)}
  1703  	}
  1704  	rq.Header.Set("Content-Type", writer.FormDataContentType())
  1705  
  1706  	if len(c.AuthToken) > 0 {
  1707  		rq.Header.Set(HEADER_AUTH, c.AuthType+" "+c.AuthToken)
  1708  	}
  1709  
  1710  	rp, err := c.HttpClient.Do(rq)
  1711  	if err != nil || rp == nil {
  1712  		return false, &Response{StatusCode: http.StatusForbidden, Error: NewAppError(c.GetBotRoute(botUserId)+"/icon", "model.client.connecting.app_error", nil, err.Error(), http.StatusForbidden)}
  1713  	}
  1714  	defer closeBody(rp)
  1715  
  1716  	if rp.StatusCode >= 300 {
  1717  		return false, BuildErrorResponse(rp, AppErrorFromJson(rp.Body))
  1718  	}
  1719  
  1720  	return CheckStatusOK(rp), BuildResponse(rp)
  1721  }
  1722  
  1723  // GetBotIconImage gets LHS bot icon image. Must be logged in.
  1724  func (c *Client4) GetBotIconImage(botUserId string) ([]byte, *Response) {
  1725  	r, appErr := c.DoApiGet(c.GetBotRoute(botUserId)+"/icon", "")
  1726  	if appErr != nil {
  1727  		return nil, BuildErrorResponse(r, appErr)
  1728  	}
  1729  	defer closeBody(r)
  1730  
  1731  	data, err := ioutil.ReadAll(r.Body)
  1732  	if err != nil {
  1733  		return nil, BuildErrorResponse(r, NewAppError("GetBotIconImage", "model.client.read_file.app_error", nil, err.Error(), r.StatusCode))
  1734  	}
  1735  	return data, BuildResponse(r)
  1736  }
  1737  
  1738  // DeleteBotIconImage deletes LHS bot icon image. Must be logged in.
  1739  func (c *Client4) DeleteBotIconImage(botUserId string) (bool, *Response) {
  1740  	r, appErr := c.DoApiDelete(c.GetBotRoute(botUserId) + "/icon")
  1741  	if appErr != nil {
  1742  		return false, BuildErrorResponse(r, appErr)
  1743  	}
  1744  	defer closeBody(r)
  1745  	return CheckStatusOK(r), BuildResponse(r)
  1746  }
  1747  
  1748  // Team Section
  1749  
  1750  // CreateTeam creates a team in the system based on the provided team struct.
  1751  func (c *Client4) CreateTeam(team *Team) (*Team, *Response) {
  1752  	r, err := c.DoApiPost(c.GetTeamsRoute(), team.ToJson())
  1753  	if err != nil {
  1754  		return nil, BuildErrorResponse(r, err)
  1755  	}
  1756  	defer closeBody(r)
  1757  	return TeamFromJson(r.Body), BuildResponse(r)
  1758  }
  1759  
  1760  // GetTeam returns a team based on the provided team id string.
  1761  func (c *Client4) GetTeam(teamId, etag string) (*Team, *Response) {
  1762  	r, err := c.DoApiGet(c.GetTeamRoute(teamId), etag)
  1763  	if err != nil {
  1764  		return nil, BuildErrorResponse(r, err)
  1765  	}
  1766  	defer closeBody(r)
  1767  	return TeamFromJson(r.Body), BuildResponse(r)
  1768  }
  1769  
  1770  // GetAllTeams returns all teams based on permissions.
  1771  func (c *Client4) GetAllTeams(etag string, page int, perPage int) ([]*Team, *Response) {
  1772  	query := fmt.Sprintf("?page=%v&per_page=%v", page, perPage)
  1773  	r, err := c.DoApiGet(c.GetTeamsRoute()+query, etag)
  1774  	if err != nil {
  1775  		return nil, BuildErrorResponse(r, err)
  1776  	}
  1777  	defer closeBody(r)
  1778  	return TeamListFromJson(r.Body), BuildResponse(r)
  1779  }
  1780  
  1781  // GetAllTeamsWithTotalCount returns all teams based on permissions.
  1782  func (c *Client4) GetAllTeamsWithTotalCount(etag string, page int, perPage int) ([]*Team, int64, *Response) {
  1783  	query := fmt.Sprintf("?page=%v&per_page=%v&include_total_count="+c.boolString(true), page, perPage)
  1784  	r, err := c.DoApiGet(c.GetTeamsRoute()+query, etag)
  1785  	if err != nil {
  1786  		return nil, 0, BuildErrorResponse(r, err)
  1787  	}
  1788  	defer closeBody(r)
  1789  	teamsListWithCount := TeamsWithCountFromJson(r.Body)
  1790  	return teamsListWithCount.Teams, teamsListWithCount.TotalCount, BuildResponse(r)
  1791  }
  1792  
  1793  // GetTeamByName returns a team based on the provided team name string.
  1794  func (c *Client4) GetTeamByName(name, etag string) (*Team, *Response) {
  1795  	r, err := c.DoApiGet(c.GetTeamByNameRoute(name), etag)
  1796  	if err != nil {
  1797  		return nil, BuildErrorResponse(r, err)
  1798  	}
  1799  	defer closeBody(r)
  1800  	return TeamFromJson(r.Body), BuildResponse(r)
  1801  }
  1802  
  1803  // SearchTeams returns teams matching the provided search term.
  1804  func (c *Client4) SearchTeams(search *TeamSearch) ([]*Team, *Response) {
  1805  	r, err := c.DoApiPost(c.GetTeamsRoute()+"/search", search.ToJson())
  1806  	if err != nil {
  1807  		return nil, BuildErrorResponse(r, err)
  1808  	}
  1809  	defer closeBody(r)
  1810  	return TeamListFromJson(r.Body), BuildResponse(r)
  1811  }
  1812  
  1813  // SearchTeamsPaged returns a page of teams and the total count matching the provided search term.
  1814  func (c *Client4) SearchTeamsPaged(search *TeamSearch) ([]*Team, int64, *Response) {
  1815  	if search.Page == nil {
  1816  		search.Page = NewInt(0)
  1817  	}
  1818  	if search.PerPage == nil {
  1819  		search.PerPage = NewInt(100)
  1820  	}
  1821  	r, err := c.DoApiPost(c.GetTeamsRoute()+"/search", search.ToJson())
  1822  	if err != nil {
  1823  		return nil, 0, BuildErrorResponse(r, err)
  1824  	}
  1825  	defer closeBody(r)
  1826  	twc := TeamsWithCountFromJson(r.Body)
  1827  	return twc.Teams, twc.TotalCount, BuildResponse(r)
  1828  }
  1829  
  1830  // TeamExists returns true or false if the team exist or not.
  1831  func (c *Client4) TeamExists(name, etag string) (bool, *Response) {
  1832  	r, err := c.DoApiGet(c.GetTeamByNameRoute(name)+"/exists", etag)
  1833  	if err != nil {
  1834  		return false, BuildErrorResponse(r, err)
  1835  	}
  1836  	defer closeBody(r)
  1837  	return MapBoolFromJson(r.Body)["exists"], BuildResponse(r)
  1838  }
  1839  
  1840  // GetTeamsForUser returns a list of teams a user is on. Must be logged in as the user
  1841  // or be a system administrator.
  1842  func (c *Client4) GetTeamsForUser(userId, etag string) ([]*Team, *Response) {
  1843  	r, err := c.DoApiGet(c.GetUserRoute(userId)+"/teams", etag)
  1844  	if err != nil {
  1845  		return nil, BuildErrorResponse(r, err)
  1846  	}
  1847  	defer closeBody(r)
  1848  	return TeamListFromJson(r.Body), BuildResponse(r)
  1849  }
  1850  
  1851  // GetTeamMember returns a team member based on the provided team and user id strings.
  1852  func (c *Client4) GetTeamMember(teamId, userId, etag string) (*TeamMember, *Response) {
  1853  	r, err := c.DoApiGet(c.GetTeamMemberRoute(teamId, userId), etag)
  1854  	if err != nil {
  1855  		return nil, BuildErrorResponse(r, err)
  1856  	}
  1857  	defer closeBody(r)
  1858  	return TeamMemberFromJson(r.Body), BuildResponse(r)
  1859  }
  1860  
  1861  // UpdateTeamMemberRoles will update the roles on a team for a user.
  1862  func (c *Client4) UpdateTeamMemberRoles(teamId, userId, newRoles string) (bool, *Response) {
  1863  	requestBody := map[string]string{"roles": newRoles}
  1864  	r, err := c.DoApiPut(c.GetTeamMemberRoute(teamId, userId)+"/roles", MapToJson(requestBody))
  1865  	if err != nil {
  1866  		return false, BuildErrorResponse(r, err)
  1867  	}
  1868  	defer closeBody(r)
  1869  	return CheckStatusOK(r), BuildResponse(r)
  1870  }
  1871  
  1872  // UpdateTeamMemberSchemeRoles will update the scheme-derived roles on a team for a user.
  1873  func (c *Client4) UpdateTeamMemberSchemeRoles(teamId string, userId string, schemeRoles *SchemeRoles) (bool, *Response) {
  1874  	r, err := c.DoApiPut(c.GetTeamMemberRoute(teamId, userId)+"/schemeRoles", schemeRoles.ToJson())
  1875  	if err != nil {
  1876  		return false, BuildErrorResponse(r, err)
  1877  	}
  1878  	defer closeBody(r)
  1879  	return CheckStatusOK(r), BuildResponse(r)
  1880  }
  1881  
  1882  // UpdateTeam will update a team.
  1883  func (c *Client4) UpdateTeam(team *Team) (*Team, *Response) {
  1884  	r, err := c.DoApiPut(c.GetTeamRoute(team.Id), team.ToJson())
  1885  	if err != nil {
  1886  		return nil, BuildErrorResponse(r, err)
  1887  	}
  1888  	defer closeBody(r)
  1889  	return TeamFromJson(r.Body), BuildResponse(r)
  1890  }
  1891  
  1892  // PatchTeam partially updates a team. Any missing fields are not updated.
  1893  func (c *Client4) PatchTeam(teamId string, patch *TeamPatch) (*Team, *Response) {
  1894  	r, err := c.DoApiPut(c.GetTeamRoute(teamId)+"/patch", patch.ToJson())
  1895  	if err != nil {
  1896  		return nil, BuildErrorResponse(r, err)
  1897  	}
  1898  	defer closeBody(r)
  1899  	return TeamFromJson(r.Body), BuildResponse(r)
  1900  }
  1901  
  1902  // RestoreTeam restores a previously deleted team.
  1903  func (c *Client4) RestoreTeam(teamId string) (*Team, *Response) {
  1904  	r, err := c.DoApiPost(c.GetTeamRoute(teamId)+"/restore", "")
  1905  	if err != nil {
  1906  		return nil, BuildErrorResponse(r, err)
  1907  	}
  1908  	defer closeBody(r)
  1909  	return TeamFromJson(r.Body), BuildResponse(r)
  1910  }
  1911  
  1912  // RegenerateTeamInviteId requests a new invite ID to be generated.
  1913  func (c *Client4) RegenerateTeamInviteId(teamId string) (*Team, *Response) {
  1914  	r, err := c.DoApiPost(c.GetTeamRoute(teamId)+"/regenerate_invite_id", "")
  1915  	if err != nil {
  1916  		return nil, BuildErrorResponse(r, err)
  1917  	}
  1918  	defer closeBody(r)
  1919  	return TeamFromJson(r.Body), BuildResponse(r)
  1920  }
  1921  
  1922  // SoftDeleteTeam deletes the team softly (archive only, not permanent delete).
  1923  func (c *Client4) SoftDeleteTeam(teamId string) (bool, *Response) {
  1924  	r, err := c.DoApiDelete(c.GetTeamRoute(teamId))
  1925  	if err != nil {
  1926  		return false, BuildErrorResponse(r, err)
  1927  	}
  1928  	defer closeBody(r)
  1929  	return CheckStatusOK(r), BuildResponse(r)
  1930  }
  1931  
  1932  // PermanentDeleteTeam deletes the team, should only be used when needed for
  1933  // compliance and the like.
  1934  func (c *Client4) PermanentDeleteTeam(teamId string) (bool, *Response) {
  1935  	r, err := c.DoApiDelete(c.GetTeamRoute(teamId) + "?permanent=" + c.boolString(true))
  1936  	if err != nil {
  1937  		return false, BuildErrorResponse(r, err)
  1938  	}
  1939  	defer closeBody(r)
  1940  	return CheckStatusOK(r), BuildResponse(r)
  1941  }
  1942  
  1943  // UpdateTeamPrivacy modifies the team type (model.TEAM_OPEN <--> model.TEAM_INVITE) and sets
  1944  // the corresponding AllowOpenInvite appropriately.
  1945  func (c *Client4) UpdateTeamPrivacy(teamId string, privacy string) (*Team, *Response) {
  1946  	requestBody := map[string]string{"privacy": privacy}
  1947  	r, err := c.DoApiPut(c.GetTeamRoute(teamId)+"/privacy", MapToJson(requestBody))
  1948  	if err != nil {
  1949  		return nil, BuildErrorResponse(r, err)
  1950  	}
  1951  	defer closeBody(r)
  1952  	return TeamFromJson(r.Body), BuildResponse(r)
  1953  }
  1954  
  1955  // GetTeamMembers returns team members based on the provided team id string.
  1956  func (c *Client4) GetTeamMembers(teamId string, page int, perPage int, etag string) ([]*TeamMember, *Response) {
  1957  	query := fmt.Sprintf("?page=%v&per_page=%v", page, perPage)
  1958  	r, err := c.DoApiGet(c.GetTeamMembersRoute(teamId)+query, etag)
  1959  	if err != nil {
  1960  		return nil, BuildErrorResponse(r, err)
  1961  	}
  1962  	defer closeBody(r)
  1963  	return TeamMembersFromJson(r.Body), BuildResponse(r)
  1964  }
  1965  
  1966  // GetTeamMembersWithoutDeletedUsers returns team members based on the provided team id string. Additional parameters of sort and exclude_deleted_users accepted as well
  1967  // Could not add it to above function due to it be a breaking change.
  1968  func (c *Client4) GetTeamMembersSortAndWithoutDeletedUsers(teamId string, page int, perPage int, sort string, exclude_deleted_users bool, etag string) ([]*TeamMember, *Response) {
  1969  	query := fmt.Sprintf("?page=%v&per_page=%v&sort=%v&exclude_deleted_users=%v", page, perPage, sort, exclude_deleted_users)
  1970  	r, err := c.DoApiGet(c.GetTeamMembersRoute(teamId)+query, etag)
  1971  	if err != nil {
  1972  		return nil, BuildErrorResponse(r, err)
  1973  	}
  1974  	defer closeBody(r)
  1975  	return TeamMembersFromJson(r.Body), BuildResponse(r)
  1976  }
  1977  
  1978  // GetTeamMembersForUser returns the team members for a user.
  1979  func (c *Client4) GetTeamMembersForUser(userId string, etag string) ([]*TeamMember, *Response) {
  1980  	r, err := c.DoApiGet(c.GetUserRoute(userId)+"/teams/members", etag)
  1981  	if err != nil {
  1982  		return nil, BuildErrorResponse(r, err)
  1983  	}
  1984  	defer closeBody(r)
  1985  	return TeamMembersFromJson(r.Body), BuildResponse(r)
  1986  }
  1987  
  1988  // GetTeamMembersByIds will return an array of team members based on the
  1989  // team id and a list of user ids provided. Must be authenticated.
  1990  func (c *Client4) GetTeamMembersByIds(teamId string, userIds []string) ([]*TeamMember, *Response) {
  1991  	r, err := c.DoApiPost(fmt.Sprintf("/teams/%v/members/ids", teamId), ArrayToJson(userIds))
  1992  	if err != nil {
  1993  		return nil, BuildErrorResponse(r, err)
  1994  	}
  1995  	defer closeBody(r)
  1996  	return TeamMembersFromJson(r.Body), BuildResponse(r)
  1997  }
  1998  
  1999  // AddTeamMember adds user to a team and return a team member.
  2000  func (c *Client4) AddTeamMember(teamId, userId string) (*TeamMember, *Response) {
  2001  	member := &TeamMember{TeamId: teamId, UserId: userId}
  2002  	r, err := c.DoApiPost(c.GetTeamMembersRoute(teamId), member.ToJson())
  2003  	if err != nil {
  2004  		return nil, BuildErrorResponse(r, err)
  2005  	}
  2006  	defer closeBody(r)
  2007  	return TeamMemberFromJson(r.Body), BuildResponse(r)
  2008  }
  2009  
  2010  // AddTeamMemberFromInvite adds a user to a team and return a team member using an invite id
  2011  // or an invite token/data pair.
  2012  func (c *Client4) AddTeamMemberFromInvite(token, inviteId string) (*TeamMember, *Response) {
  2013  	var query string
  2014  
  2015  	if inviteId != "" {
  2016  		query += fmt.Sprintf("?invite_id=%v", inviteId)
  2017  	}
  2018  
  2019  	if token != "" {
  2020  		query += fmt.Sprintf("?token=%v", token)
  2021  	}
  2022  
  2023  	r, err := c.DoApiPost(c.GetTeamsRoute()+"/members/invite"+query, "")
  2024  	if err != nil {
  2025  		return nil, BuildErrorResponse(r, err)
  2026  	}
  2027  	defer closeBody(r)
  2028  	return TeamMemberFromJson(r.Body), BuildResponse(r)
  2029  }
  2030  
  2031  // AddTeamMembers adds a number of users to a team and returns the team members.
  2032  func (c *Client4) AddTeamMembers(teamId string, userIds []string) ([]*TeamMember, *Response) {
  2033  	var members []*TeamMember
  2034  	for _, userId := range userIds {
  2035  		member := &TeamMember{TeamId: teamId, UserId: userId}
  2036  		members = append(members, member)
  2037  	}
  2038  
  2039  	r, err := c.DoApiPost(c.GetTeamMembersRoute(teamId)+"/batch", TeamMembersToJson(members))
  2040  	if err != nil {
  2041  		return nil, BuildErrorResponse(r, err)
  2042  	}
  2043  	defer closeBody(r)
  2044  	return TeamMembersFromJson(r.Body), BuildResponse(r)
  2045  }
  2046  
  2047  // AddTeamMembers adds a number of users to a team and returns the team members.
  2048  func (c *Client4) AddTeamMembersGracefully(teamId string, userIds []string) ([]*TeamMemberWithError, *Response) {
  2049  	var members []*TeamMember
  2050  	for _, userId := range userIds {
  2051  		member := &TeamMember{TeamId: teamId, UserId: userId}
  2052  		members = append(members, member)
  2053  	}
  2054  
  2055  	r, err := c.DoApiPost(c.GetTeamMembersRoute(teamId)+"/batch?graceful="+c.boolString(true), TeamMembersToJson(members))
  2056  	if err != nil {
  2057  		return nil, BuildErrorResponse(r, err)
  2058  	}
  2059  	defer closeBody(r)
  2060  	return TeamMembersWithErrorFromJson(r.Body), BuildResponse(r)
  2061  }
  2062  
  2063  // RemoveTeamMember will remove a user from a team.
  2064  func (c *Client4) RemoveTeamMember(teamId, userId string) (bool, *Response) {
  2065  	r, err := c.DoApiDelete(c.GetTeamMemberRoute(teamId, userId))
  2066  	if err != nil {
  2067  		return false, BuildErrorResponse(r, err)
  2068  	}
  2069  	defer closeBody(r)
  2070  	return CheckStatusOK(r), BuildResponse(r)
  2071  }
  2072  
  2073  // GetTeamStats returns a team stats based on the team id string.
  2074  // Must be authenticated.
  2075  func (c *Client4) GetTeamStats(teamId, etag string) (*TeamStats, *Response) {
  2076  	r, err := c.DoApiGet(c.GetTeamStatsRoute(teamId), etag)
  2077  	if err != nil {
  2078  		return nil, BuildErrorResponse(r, err)
  2079  	}
  2080  	defer closeBody(r)
  2081  	return TeamStatsFromJson(r.Body), BuildResponse(r)
  2082  }
  2083  
  2084  // GetTotalUsersStats returns a total system user stats.
  2085  // Must be authenticated.
  2086  func (c *Client4) GetTotalUsersStats(etag string) (*UsersStats, *Response) {
  2087  	r, err := c.DoApiGet(c.GetTotalUsersStatsRoute(), etag)
  2088  	if err != nil {
  2089  		return nil, BuildErrorResponse(r, err)
  2090  	}
  2091  	defer closeBody(r)
  2092  	return UsersStatsFromJson(r.Body), BuildResponse(r)
  2093  }
  2094  
  2095  // GetTeamUnread will return a TeamUnread object that contains the amount of
  2096  // unread messages and mentions the user has for the specified team.
  2097  // Must be authenticated.
  2098  func (c *Client4) GetTeamUnread(teamId, userId string) (*TeamUnread, *Response) {
  2099  	r, err := c.DoApiGet(c.GetUserRoute(userId)+c.GetTeamRoute(teamId)+"/unread", "")
  2100  	if err != nil {
  2101  		return nil, BuildErrorResponse(r, err)
  2102  	}
  2103  	defer closeBody(r)
  2104  	return TeamUnreadFromJson(r.Body), BuildResponse(r)
  2105  }
  2106  
  2107  // ImportTeam will import an exported team from other app into a existing team.
  2108  func (c *Client4) ImportTeam(data []byte, filesize int, importFrom, filename, teamId string) (map[string]string, *Response) {
  2109  	body := &bytes.Buffer{}
  2110  	writer := multipart.NewWriter(body)
  2111  
  2112  	part, err := writer.CreateFormFile("file", filename)
  2113  	if err != nil {
  2114  		return nil, &Response{Error: NewAppError("UploadImportTeam", "model.client.upload_post_attachment.file.app_error", nil, err.Error(), http.StatusBadRequest)}
  2115  	}
  2116  
  2117  	if _, err = io.Copy(part, bytes.NewBuffer(data)); err != nil {
  2118  		return nil, &Response{Error: NewAppError("UploadImportTeam", "model.client.upload_post_attachment.file.app_error", nil, err.Error(), http.StatusBadRequest)}
  2119  	}
  2120  
  2121  	part, err = writer.CreateFormField("filesize")
  2122  	if err != nil {
  2123  		return nil, &Response{Error: NewAppError("UploadImportTeam", "model.client.upload_post_attachment.file_size.app_error", nil, err.Error(), http.StatusBadRequest)}
  2124  	}
  2125  
  2126  	if _, err = io.Copy(part, strings.NewReader(strconv.Itoa(filesize))); err != nil {
  2127  		return nil, &Response{Error: NewAppError("UploadImportTeam", "model.client.upload_post_attachment.file_size.app_error", nil, err.Error(), http.StatusBadRequest)}
  2128  	}
  2129  
  2130  	part, err = writer.CreateFormField("importFrom")
  2131  	if err != nil {
  2132  		return nil, &Response{Error: NewAppError("UploadImportTeam", "model.client.upload_post_attachment.import_from.app_error", nil, err.Error(), http.StatusBadRequest)}
  2133  	}
  2134  
  2135  	if _, err := io.Copy(part, strings.NewReader(importFrom)); err != nil {
  2136  		return nil, &Response{Error: NewAppError("UploadImportTeam", "model.client.upload_post_attachment.import_from.app_error", nil, err.Error(), http.StatusBadRequest)}
  2137  	}
  2138  
  2139  	if err := writer.Close(); err != nil {
  2140  		return nil, &Response{Error: NewAppError("UploadImportTeam", "model.client.upload_post_attachment.writer.app_error", nil, err.Error(), http.StatusBadRequest)}
  2141  	}
  2142  
  2143  	return c.DoUploadImportTeam(c.GetTeamImportRoute(teamId), body.Bytes(), writer.FormDataContentType())
  2144  }
  2145  
  2146  // InviteUsersToTeam invite users by email to the team.
  2147  func (c *Client4) InviteUsersToTeam(teamId string, userEmails []string) (bool, *Response) {
  2148  	r, err := c.DoApiPost(c.GetTeamRoute(teamId)+"/invite/email", ArrayToJson(userEmails))
  2149  	if err != nil {
  2150  		return false, BuildErrorResponse(r, err)
  2151  	}
  2152  	defer closeBody(r)
  2153  	return CheckStatusOK(r), BuildResponse(r)
  2154  }
  2155  
  2156  // InviteGuestsToTeam invite guest by email to some channels in a team.
  2157  func (c *Client4) InviteGuestsToTeam(teamId string, userEmails []string, channels []string, message string) (bool, *Response) {
  2158  	guestsInvite := GuestsInvite{
  2159  		Emails:   userEmails,
  2160  		Channels: channels,
  2161  		Message:  message,
  2162  	}
  2163  	r, err := c.DoApiPost(c.GetTeamRoute(teamId)+"/invite-guests/email", guestsInvite.ToJson())
  2164  	if err != nil {
  2165  		return false, BuildErrorResponse(r, err)
  2166  	}
  2167  	defer closeBody(r)
  2168  	return CheckStatusOK(r), BuildResponse(r)
  2169  }
  2170  
  2171  // InviteUsersToTeam invite users by email to the team.
  2172  func (c *Client4) InviteUsersToTeamGracefully(teamId string, userEmails []string) ([]*EmailInviteWithError, *Response) {
  2173  	r, err := c.DoApiPost(c.GetTeamRoute(teamId)+"/invite/email?graceful="+c.boolString(true), ArrayToJson(userEmails))
  2174  	if err != nil {
  2175  		return nil, BuildErrorResponse(r, err)
  2176  	}
  2177  	defer closeBody(r)
  2178  	return EmailInviteWithErrorFromJson(r.Body), BuildResponse(r)
  2179  }
  2180  
  2181  // InviteGuestsToTeam invite guest by email to some channels in a team.
  2182  func (c *Client4) InviteGuestsToTeamGracefully(teamId string, userEmails []string, channels []string, message string) ([]*EmailInviteWithError, *Response) {
  2183  	guestsInvite := GuestsInvite{
  2184  		Emails:   userEmails,
  2185  		Channels: channels,
  2186  		Message:  message,
  2187  	}
  2188  	r, err := c.DoApiPost(c.GetTeamRoute(teamId)+"/invite-guests/email?graceful="+c.boolString(true), guestsInvite.ToJson())
  2189  	if err != nil {
  2190  		return nil, BuildErrorResponse(r, err)
  2191  	}
  2192  	defer closeBody(r)
  2193  	return EmailInviteWithErrorFromJson(r.Body), BuildResponse(r)
  2194  }
  2195  
  2196  // InvalidateEmailInvites will invalidate active email invitations that have not been accepted by the user.
  2197  func (c *Client4) InvalidateEmailInvites() (bool, *Response) {
  2198  	r, err := c.DoApiDelete(c.GetTeamsRoute() + "/invites/email")
  2199  	if err != nil {
  2200  		return false, BuildErrorResponse(r, err)
  2201  	}
  2202  	defer closeBody(r)
  2203  	return CheckStatusOK(r), BuildResponse(r)
  2204  }
  2205  
  2206  // GetTeamInviteInfo returns a team object from an invite id containing sanitized information.
  2207  func (c *Client4) GetTeamInviteInfo(inviteId string) (*Team, *Response) {
  2208  	r, err := c.DoApiGet(c.GetTeamsRoute()+"/invite/"+inviteId, "")
  2209  	if err != nil {
  2210  		return nil, BuildErrorResponse(r, err)
  2211  	}
  2212  	defer closeBody(r)
  2213  	return TeamFromJson(r.Body), BuildResponse(r)
  2214  }
  2215  
  2216  // SetTeamIcon sets team icon of the team.
  2217  func (c *Client4) SetTeamIcon(teamId string, data []byte) (bool, *Response) {
  2218  	body := &bytes.Buffer{}
  2219  	writer := multipart.NewWriter(body)
  2220  
  2221  	part, err := writer.CreateFormFile("image", "teamIcon.png")
  2222  	if err != nil {
  2223  		return false, &Response{Error: NewAppError("SetTeamIcon", "model.client.set_team_icon.no_file.app_error", nil, err.Error(), http.StatusBadRequest)}
  2224  	}
  2225  
  2226  	if _, err = io.Copy(part, bytes.NewBuffer(data)); err != nil {
  2227  		return false, &Response{Error: NewAppError("SetTeamIcon", "model.client.set_team_icon.no_file.app_error", nil, err.Error(), http.StatusBadRequest)}
  2228  	}
  2229  
  2230  	if err = writer.Close(); err != nil {
  2231  		return false, &Response{Error: NewAppError("SetTeamIcon", "model.client.set_team_icon.writer.app_error", nil, err.Error(), http.StatusBadRequest)}
  2232  	}
  2233  
  2234  	rq, err := http.NewRequest("POST", c.ApiUrl+c.GetTeamRoute(teamId)+"/image", bytes.NewReader(body.Bytes()))
  2235  	if err != nil {
  2236  		return false, &Response{Error: NewAppError("SetTeamIcon", "model.client.connecting.app_error", nil, err.Error(), http.StatusBadRequest)}
  2237  	}
  2238  	rq.Header.Set("Content-Type", writer.FormDataContentType())
  2239  
  2240  	if len(c.AuthToken) > 0 {
  2241  		rq.Header.Set(HEADER_AUTH, c.AuthType+" "+c.AuthToken)
  2242  	}
  2243  
  2244  	rp, err := c.HttpClient.Do(rq)
  2245  	if err != nil || rp == nil {
  2246  		// set to http.StatusForbidden(403)
  2247  		return false, &Response{StatusCode: http.StatusForbidden, Error: NewAppError(c.GetTeamRoute(teamId)+"/image", "model.client.connecting.app_error", nil, err.Error(), 403)}
  2248  	}
  2249  	defer closeBody(rp)
  2250  
  2251  	if rp.StatusCode >= 300 {
  2252  		return false, BuildErrorResponse(rp, AppErrorFromJson(rp.Body))
  2253  	}
  2254  
  2255  	return CheckStatusOK(rp), BuildResponse(rp)
  2256  }
  2257  
  2258  // GetTeamIcon gets the team icon of the team.
  2259  func (c *Client4) GetTeamIcon(teamId, etag string) ([]byte, *Response) {
  2260  	r, appErr := c.DoApiGet(c.GetTeamRoute(teamId)+"/image", etag)
  2261  	if appErr != nil {
  2262  		return nil, BuildErrorResponse(r, appErr)
  2263  	}
  2264  	defer closeBody(r)
  2265  
  2266  	data, err := ioutil.ReadAll(r.Body)
  2267  	if err != nil {
  2268  		return nil, BuildErrorResponse(r, NewAppError("GetTeamIcon", "model.client.get_team_icon.app_error", nil, err.Error(), r.StatusCode))
  2269  	}
  2270  	return data, BuildResponse(r)
  2271  }
  2272  
  2273  // RemoveTeamIcon updates LastTeamIconUpdate to 0 which indicates team icon is removed.
  2274  func (c *Client4) RemoveTeamIcon(teamId string) (bool, *Response) {
  2275  	r, err := c.DoApiDelete(c.GetTeamRoute(teamId) + "/image")
  2276  	if err != nil {
  2277  		return false, BuildErrorResponse(r, err)
  2278  	}
  2279  	defer closeBody(r)
  2280  	return CheckStatusOK(r), BuildResponse(r)
  2281  }
  2282  
  2283  // Channel Section
  2284  
  2285  // GetAllChannels get all the channels. Must be a system administrator.
  2286  func (c *Client4) GetAllChannels(page int, perPage int, etag string) (*ChannelListWithTeamData, *Response) {
  2287  	return c.getAllChannels(page, perPage, etag, false)
  2288  }
  2289  
  2290  // GetAllChannelsIncludeDeleted get all the channels. Must be a system administrator.
  2291  func (c *Client4) GetAllChannelsIncludeDeleted(page int, perPage int, etag string) (*ChannelListWithTeamData, *Response) {
  2292  	return c.getAllChannels(page, perPage, etag, true)
  2293  }
  2294  
  2295  func (c *Client4) getAllChannels(page int, perPage int, etag string, includeDeleted bool) (*ChannelListWithTeamData, *Response) {
  2296  	query := fmt.Sprintf("?page=%v&per_page=%v&include_deleted=%v", page, perPage, includeDeleted)
  2297  	r, err := c.DoApiGet(c.GetChannelsRoute()+query, etag)
  2298  	if err != nil {
  2299  		return nil, BuildErrorResponse(r, err)
  2300  	}
  2301  	defer closeBody(r)
  2302  	return ChannelListWithTeamDataFromJson(r.Body), BuildResponse(r)
  2303  }
  2304  
  2305  // GetAllChannelsWithCount get all the channels including the total count. Must be a system administrator.
  2306  func (c *Client4) GetAllChannelsWithCount(page int, perPage int, etag string) (*ChannelListWithTeamData, int64, *Response) {
  2307  	query := fmt.Sprintf("?page=%v&per_page=%v&include_total_count="+c.boolString(true), page, perPage)
  2308  	r, err := c.DoApiGet(c.GetChannelsRoute()+query, etag)
  2309  	if err != nil {
  2310  		return nil, 0, BuildErrorResponse(r, err)
  2311  	}
  2312  	defer closeBody(r)
  2313  	cwc := ChannelsWithCountFromJson(r.Body)
  2314  	return cwc.Channels, cwc.TotalCount, BuildResponse(r)
  2315  }
  2316  
  2317  // CreateChannel creates a channel based on the provided channel struct.
  2318  func (c *Client4) CreateChannel(channel *Channel) (*Channel, *Response) {
  2319  	r, err := c.DoApiPost(c.GetChannelsRoute(), channel.ToJson())
  2320  	if err != nil {
  2321  		return nil, BuildErrorResponse(r, err)
  2322  	}
  2323  	defer closeBody(r)
  2324  	return ChannelFromJson(r.Body), BuildResponse(r)
  2325  }
  2326  
  2327  // UpdateChannel updates a channel based on the provided channel struct.
  2328  func (c *Client4) UpdateChannel(channel *Channel) (*Channel, *Response) {
  2329  	r, err := c.DoApiPut(c.GetChannelRoute(channel.Id), channel.ToJson())
  2330  	if err != nil {
  2331  		return nil, BuildErrorResponse(r, err)
  2332  	}
  2333  	defer closeBody(r)
  2334  	return ChannelFromJson(r.Body), BuildResponse(r)
  2335  }
  2336  
  2337  // PatchChannel partially updates a channel. Any missing fields are not updated.
  2338  func (c *Client4) PatchChannel(channelId string, patch *ChannelPatch) (*Channel, *Response) {
  2339  	r, err := c.DoApiPut(c.GetChannelRoute(channelId)+"/patch", patch.ToJson())
  2340  	if err != nil {
  2341  		return nil, BuildErrorResponse(r, err)
  2342  	}
  2343  	defer closeBody(r)
  2344  	return ChannelFromJson(r.Body), BuildResponse(r)
  2345  }
  2346  
  2347  // ConvertChannelToPrivate converts public to private channel.
  2348  func (c *Client4) ConvertChannelToPrivate(channelId string) (*Channel, *Response) {
  2349  	r, err := c.DoApiPost(c.GetChannelRoute(channelId)+"/convert", "")
  2350  	if err != nil {
  2351  		return nil, BuildErrorResponse(r, err)
  2352  	}
  2353  	defer closeBody(r)
  2354  	return ChannelFromJson(r.Body), BuildResponse(r)
  2355  }
  2356  
  2357  // UpdateChannelPrivacy updates channel privacy
  2358  func (c *Client4) UpdateChannelPrivacy(channelId string, privacy string) (*Channel, *Response) {
  2359  	requestBody := map[string]string{"privacy": privacy}
  2360  	r, err := c.DoApiPut(c.GetChannelRoute(channelId)+"/privacy", MapToJson(requestBody))
  2361  	if err != nil {
  2362  		return nil, BuildErrorResponse(r, err)
  2363  	}
  2364  	defer closeBody(r)
  2365  	return ChannelFromJson(r.Body), BuildResponse(r)
  2366  }
  2367  
  2368  // RestoreChannel restores a previously deleted channel. Any missing fields are not updated.
  2369  func (c *Client4) RestoreChannel(channelId string) (*Channel, *Response) {
  2370  	r, err := c.DoApiPost(c.GetChannelRoute(channelId)+"/restore", "")
  2371  	if err != nil {
  2372  		return nil, BuildErrorResponse(r, err)
  2373  	}
  2374  	defer closeBody(r)
  2375  	return ChannelFromJson(r.Body), BuildResponse(r)
  2376  }
  2377  
  2378  // CreateDirectChannel creates a direct message channel based on the two user
  2379  // ids provided.
  2380  func (c *Client4) CreateDirectChannel(userId1, userId2 string) (*Channel, *Response) {
  2381  	requestBody := []string{userId1, userId2}
  2382  	r, err := c.DoApiPost(c.GetChannelsRoute()+"/direct", ArrayToJson(requestBody))
  2383  	if err != nil {
  2384  		return nil, BuildErrorResponse(r, err)
  2385  	}
  2386  	defer closeBody(r)
  2387  	return ChannelFromJson(r.Body), BuildResponse(r)
  2388  }
  2389  
  2390  // CreateGroupChannel creates a group message channel based on userIds provided.
  2391  func (c *Client4) CreateGroupChannel(userIds []string) (*Channel, *Response) {
  2392  	r, err := c.DoApiPost(c.GetChannelsRoute()+"/group", ArrayToJson(userIds))
  2393  	if err != nil {
  2394  		return nil, BuildErrorResponse(r, err)
  2395  	}
  2396  	defer closeBody(r)
  2397  	return ChannelFromJson(r.Body), BuildResponse(r)
  2398  }
  2399  
  2400  // GetChannel returns a channel based on the provided channel id string.
  2401  func (c *Client4) GetChannel(channelId, etag string) (*Channel, *Response) {
  2402  	r, err := c.DoApiGet(c.GetChannelRoute(channelId), etag)
  2403  	if err != nil {
  2404  		return nil, BuildErrorResponse(r, err)
  2405  	}
  2406  	defer closeBody(r)
  2407  	return ChannelFromJson(r.Body), BuildResponse(r)
  2408  }
  2409  
  2410  // GetChannelStats returns statistics for a channel.
  2411  func (c *Client4) GetChannelStats(channelId string, etag string) (*ChannelStats, *Response) {
  2412  	r, err := c.DoApiGet(c.GetChannelRoute(channelId)+"/stats", etag)
  2413  	if err != nil {
  2414  		return nil, BuildErrorResponse(r, err)
  2415  	}
  2416  	defer closeBody(r)
  2417  	return ChannelStatsFromJson(r.Body), BuildResponse(r)
  2418  }
  2419  
  2420  // GetChannelMembersTimezones gets a list of timezones for a channel.
  2421  func (c *Client4) GetChannelMembersTimezones(channelId string) ([]string, *Response) {
  2422  	r, err := c.DoApiGet(c.GetChannelRoute(channelId)+"/timezones", "")
  2423  	if err != nil {
  2424  		return nil, BuildErrorResponse(r, err)
  2425  	}
  2426  	defer closeBody(r)
  2427  	return ArrayFromJson(r.Body), BuildResponse(r)
  2428  }
  2429  
  2430  // GetPinnedPosts gets a list of pinned posts.
  2431  func (c *Client4) GetPinnedPosts(channelId string, etag string) (*PostList, *Response) {
  2432  	r, err := c.DoApiGet(c.GetChannelRoute(channelId)+"/pinned", etag)
  2433  	if err != nil {
  2434  		return nil, BuildErrorResponse(r, err)
  2435  	}
  2436  	defer closeBody(r)
  2437  	return PostListFromJson(r.Body), BuildResponse(r)
  2438  }
  2439  
  2440  // GetPrivateChannelsForTeam returns a list of private channels based on the provided team id string.
  2441  func (c *Client4) GetPrivateChannelsForTeam(teamId string, page int, perPage int, etag string) ([]*Channel, *Response) {
  2442  	query := fmt.Sprintf("/private?page=%v&per_page=%v", page, perPage)
  2443  	r, err := c.DoApiGet(c.GetChannelsForTeamRoute(teamId)+query, etag)
  2444  	if err != nil {
  2445  		return nil, BuildErrorResponse(r, err)
  2446  	}
  2447  	defer closeBody(r)
  2448  	return ChannelSliceFromJson(r.Body), BuildResponse(r)
  2449  }
  2450  
  2451  // GetPublicChannelsForTeam returns a list of public channels based on the provided team id string.
  2452  func (c *Client4) GetPublicChannelsForTeam(teamId string, page int, perPage int, etag string) ([]*Channel, *Response) {
  2453  	query := fmt.Sprintf("?page=%v&per_page=%v", page, perPage)
  2454  	r, err := c.DoApiGet(c.GetChannelsForTeamRoute(teamId)+query, etag)
  2455  	if err != nil {
  2456  		return nil, BuildErrorResponse(r, err)
  2457  	}
  2458  	defer closeBody(r)
  2459  	return ChannelSliceFromJson(r.Body), BuildResponse(r)
  2460  }
  2461  
  2462  // GetDeletedChannelsForTeam returns a list of public channels based on the provided team id string.
  2463  func (c *Client4) GetDeletedChannelsForTeam(teamId string, page int, perPage int, etag string) ([]*Channel, *Response) {
  2464  	query := fmt.Sprintf("/deleted?page=%v&per_page=%v", page, perPage)
  2465  	r, err := c.DoApiGet(c.GetChannelsForTeamRoute(teamId)+query, etag)
  2466  	if err != nil {
  2467  		return nil, BuildErrorResponse(r, err)
  2468  	}
  2469  	defer closeBody(r)
  2470  	return ChannelSliceFromJson(r.Body), BuildResponse(r)
  2471  }
  2472  
  2473  // GetPublicChannelsByIdsForTeam returns a list of public channels based on provided team id string.
  2474  func (c *Client4) GetPublicChannelsByIdsForTeam(teamId string, channelIds []string) ([]*Channel, *Response) {
  2475  	r, err := c.DoApiPost(c.GetChannelsForTeamRoute(teamId)+"/ids", ArrayToJson(channelIds))
  2476  	if err != nil {
  2477  		return nil, BuildErrorResponse(r, err)
  2478  	}
  2479  	defer closeBody(r)
  2480  	return ChannelSliceFromJson(r.Body), BuildResponse(r)
  2481  }
  2482  
  2483  // GetChannelsForTeamForUser returns a list channels of on a team for a user.
  2484  func (c *Client4) GetChannelsForTeamForUser(teamId, userId string, includeDeleted bool, etag string) ([]*Channel, *Response) {
  2485  	r, err := c.DoApiGet(c.GetChannelsForTeamForUserRoute(teamId, userId, includeDeleted), etag)
  2486  	if err != nil {
  2487  		return nil, BuildErrorResponse(r, err)
  2488  	}
  2489  	defer closeBody(r)
  2490  	return ChannelSliceFromJson(r.Body), BuildResponse(r)
  2491  }
  2492  
  2493  // GetChannelsForTeamAndUserWithLastDeleteAt returns a list channels of a team for a user, additionally filtered with lastDeleteAt. This does not have any effect if includeDeleted is set to false.
  2494  func (c *Client4) GetChannelsForTeamAndUserWithLastDeleteAt(teamId, userId string, includeDeleted bool, lastDeleteAt int, etag string) ([]*Channel, *Response) {
  2495  	route := fmt.Sprintf(c.GetUserRoute(userId) + c.GetTeamRoute(teamId) + "/channels")
  2496  	route += fmt.Sprintf("?include_deleted=%v&last_delete_at=%d", includeDeleted, lastDeleteAt)
  2497  	r, err := c.DoApiGet(route, etag)
  2498  	if err != nil {
  2499  		return nil, BuildErrorResponse(r, err)
  2500  	}
  2501  	defer closeBody(r)
  2502  	return ChannelSliceFromJson(r.Body), BuildResponse(r)
  2503  }
  2504  
  2505  // SearchChannels returns the channels on a team matching the provided search term.
  2506  func (c *Client4) SearchChannels(teamId string, search *ChannelSearch) ([]*Channel, *Response) {
  2507  	r, err := c.DoApiPost(c.GetChannelsForTeamRoute(teamId)+"/search", search.ToJson())
  2508  	if err != nil {
  2509  		return nil, BuildErrorResponse(r, err)
  2510  	}
  2511  	defer closeBody(r)
  2512  	return ChannelSliceFromJson(r.Body), BuildResponse(r)
  2513  }
  2514  
  2515  // SearchArchivedChannels returns the archived channels on a team matching the provided search term.
  2516  func (c *Client4) SearchArchivedChannels(teamId string, search *ChannelSearch) ([]*Channel, *Response) {
  2517  	r, err := c.DoApiPost(c.GetChannelsForTeamRoute(teamId)+"/search_archived", search.ToJson())
  2518  	if err != nil {
  2519  		return nil, BuildErrorResponse(r, err)
  2520  	}
  2521  	defer closeBody(r)
  2522  	return ChannelSliceFromJson(r.Body), BuildResponse(r)
  2523  }
  2524  
  2525  // SearchAllChannels search in all the channels. Must be a system administrator.
  2526  func (c *Client4) SearchAllChannels(search *ChannelSearch) (*ChannelListWithTeamData, *Response) {
  2527  	r, err := c.DoApiPost(c.GetChannelsRoute()+"/search", search.ToJson())
  2528  	if err != nil {
  2529  		return nil, BuildErrorResponse(r, err)
  2530  	}
  2531  	defer closeBody(r)
  2532  	return ChannelListWithTeamDataFromJson(r.Body), BuildResponse(r)
  2533  }
  2534  
  2535  // SearchAllChannelsPaged searches all the channels and returns the results paged with the total count.
  2536  func (c *Client4) SearchAllChannelsPaged(search *ChannelSearch) (*ChannelsWithCount, *Response) {
  2537  	r, err := c.DoApiPost(c.GetChannelsRoute()+"/search", search.ToJson())
  2538  	if err != nil {
  2539  		return nil, BuildErrorResponse(r, err)
  2540  	}
  2541  	defer closeBody(r)
  2542  	return ChannelsWithCountFromJson(r.Body), BuildResponse(r)
  2543  }
  2544  
  2545  // SearchGroupChannels returns the group channels of the user whose members' usernames match the search term.
  2546  func (c *Client4) SearchGroupChannels(search *ChannelSearch) ([]*Channel, *Response) {
  2547  	r, err := c.DoApiPost(c.GetChannelsRoute()+"/group/search", search.ToJson())
  2548  	if err != nil {
  2549  		return nil, BuildErrorResponse(r, err)
  2550  	}
  2551  	defer closeBody(r)
  2552  	return ChannelSliceFromJson(r.Body), BuildResponse(r)
  2553  }
  2554  
  2555  // DeleteChannel deletes channel based on the provided channel id string.
  2556  func (c *Client4) DeleteChannel(channelId string) (bool, *Response) {
  2557  	r, err := c.DoApiDelete(c.GetChannelRoute(channelId))
  2558  	if err != nil {
  2559  		return false, BuildErrorResponse(r, err)
  2560  	}
  2561  	defer closeBody(r)
  2562  	return CheckStatusOK(r), BuildResponse(r)
  2563  }
  2564  
  2565  // MoveChannel moves the channel to the destination team.
  2566  func (c *Client4) MoveChannel(channelId, teamId string, force bool) (*Channel, *Response) {
  2567  	requestBody := map[string]interface{}{
  2568  		"team_id": teamId,
  2569  		"force":   force,
  2570  	}
  2571  	r, err := c.DoApiPost(c.GetChannelRoute(channelId)+"/move", StringInterfaceToJson(requestBody))
  2572  	if err != nil {
  2573  		return nil, BuildErrorResponse(r, err)
  2574  	}
  2575  	defer closeBody(r)
  2576  	return ChannelFromJson(r.Body), BuildResponse(r)
  2577  }
  2578  
  2579  // GetChannelByName returns a channel based on the provided channel name and team id strings.
  2580  func (c *Client4) GetChannelByName(channelName, teamId string, etag string) (*Channel, *Response) {
  2581  	r, err := c.DoApiGet(c.GetChannelByNameRoute(channelName, teamId), etag)
  2582  	if err != nil {
  2583  		return nil, BuildErrorResponse(r, err)
  2584  	}
  2585  	defer closeBody(r)
  2586  	return ChannelFromJson(r.Body), BuildResponse(r)
  2587  }
  2588  
  2589  // GetChannelByNameIncludeDeleted returns a channel based on the provided channel name and team id strings. Other then GetChannelByName it will also return deleted channels.
  2590  func (c *Client4) GetChannelByNameIncludeDeleted(channelName, teamId string, etag string) (*Channel, *Response) {
  2591  	r, err := c.DoApiGet(c.GetChannelByNameRoute(channelName, teamId)+"?include_deleted="+c.boolString(true), etag)
  2592  	if err != nil {
  2593  		return nil, BuildErrorResponse(r, err)
  2594  	}
  2595  	defer closeBody(r)
  2596  	return ChannelFromJson(r.Body), BuildResponse(r)
  2597  }
  2598  
  2599  // GetChannelByNameForTeamName returns a channel based on the provided channel name and team name strings.
  2600  func (c *Client4) GetChannelByNameForTeamName(channelName, teamName string, etag string) (*Channel, *Response) {
  2601  	r, err := c.DoApiGet(c.GetChannelByNameForTeamNameRoute(channelName, teamName), etag)
  2602  	if err != nil {
  2603  		return nil, BuildErrorResponse(r, err)
  2604  	}
  2605  	defer closeBody(r)
  2606  	return ChannelFromJson(r.Body), BuildResponse(r)
  2607  }
  2608  
  2609  // GetChannelByNameForTeamNameIncludeDeleted returns a channel based on the provided channel name and team name strings. Other then GetChannelByNameForTeamName it will also return deleted channels.
  2610  func (c *Client4) GetChannelByNameForTeamNameIncludeDeleted(channelName, teamName string, etag string) (*Channel, *Response) {
  2611  	r, err := c.DoApiGet(c.GetChannelByNameForTeamNameRoute(channelName, teamName)+"?include_deleted="+c.boolString(true), etag)
  2612  	if err != nil {
  2613  		return nil, BuildErrorResponse(r, err)
  2614  	}
  2615  	defer closeBody(r)
  2616  	return ChannelFromJson(r.Body), BuildResponse(r)
  2617  }
  2618  
  2619  // GetChannelMembers gets a page of channel members.
  2620  func (c *Client4) GetChannelMembers(channelId string, page, perPage int, etag string) (*ChannelMembers, *Response) {
  2621  	query := fmt.Sprintf("?page=%v&per_page=%v", page, perPage)
  2622  	r, err := c.DoApiGet(c.GetChannelMembersRoute(channelId)+query, etag)
  2623  	if err != nil {
  2624  		return nil, BuildErrorResponse(r, err)
  2625  	}
  2626  	defer closeBody(r)
  2627  	return ChannelMembersFromJson(r.Body), BuildResponse(r)
  2628  }
  2629  
  2630  // GetChannelMembersByIds gets the channel members in a channel for a list of user ids.
  2631  func (c *Client4) GetChannelMembersByIds(channelId string, userIds []string) (*ChannelMembers, *Response) {
  2632  	r, err := c.DoApiPost(c.GetChannelMembersRoute(channelId)+"/ids", ArrayToJson(userIds))
  2633  	if err != nil {
  2634  		return nil, BuildErrorResponse(r, err)
  2635  	}
  2636  	defer closeBody(r)
  2637  	return ChannelMembersFromJson(r.Body), BuildResponse(r)
  2638  }
  2639  
  2640  // GetChannelMember gets a channel member.
  2641  func (c *Client4) GetChannelMember(channelId, userId, etag string) (*ChannelMember, *Response) {
  2642  	r, err := c.DoApiGet(c.GetChannelMemberRoute(channelId, userId), etag)
  2643  	if err != nil {
  2644  		return nil, BuildErrorResponse(r, err)
  2645  	}
  2646  	defer closeBody(r)
  2647  	return ChannelMemberFromJson(r.Body), BuildResponse(r)
  2648  }
  2649  
  2650  // GetChannelMembersForUser gets all the channel members for a user on a team.
  2651  func (c *Client4) GetChannelMembersForUser(userId, teamId, etag string) (*ChannelMembers, *Response) {
  2652  	r, err := c.DoApiGet(fmt.Sprintf(c.GetUserRoute(userId)+"/teams/%v/channels/members", teamId), etag)
  2653  	if err != nil {
  2654  		return nil, BuildErrorResponse(r, err)
  2655  	}
  2656  	defer closeBody(r)
  2657  	return ChannelMembersFromJson(r.Body), BuildResponse(r)
  2658  }
  2659  
  2660  // ViewChannel performs a view action for a user. Synonymous with switching channels or marking channels as read by a user.
  2661  func (c *Client4) ViewChannel(userId string, view *ChannelView) (*ChannelViewResponse, *Response) {
  2662  	url := fmt.Sprintf(c.GetChannelsRoute()+"/members/%v/view", userId)
  2663  	r, err := c.DoApiPost(url, view.ToJson())
  2664  	if err != nil {
  2665  		return nil, BuildErrorResponse(r, err)
  2666  	}
  2667  	defer closeBody(r)
  2668  	return ChannelViewResponseFromJson(r.Body), BuildResponse(r)
  2669  }
  2670  
  2671  // GetChannelUnread will return a ChannelUnread object that contains the number of
  2672  // unread messages and mentions for a user.
  2673  func (c *Client4) GetChannelUnread(channelId, userId string) (*ChannelUnread, *Response) {
  2674  	r, err := c.DoApiGet(c.GetUserRoute(userId)+c.GetChannelRoute(channelId)+"/unread", "")
  2675  	if err != nil {
  2676  		return nil, BuildErrorResponse(r, err)
  2677  	}
  2678  	defer closeBody(r)
  2679  	return ChannelUnreadFromJson(r.Body), BuildResponse(r)
  2680  }
  2681  
  2682  // UpdateChannelRoles will update the roles on a channel for a user.
  2683  func (c *Client4) UpdateChannelRoles(channelId, userId, roles string) (bool, *Response) {
  2684  	requestBody := map[string]string{"roles": roles}
  2685  	r, err := c.DoApiPut(c.GetChannelMemberRoute(channelId, userId)+"/roles", MapToJson(requestBody))
  2686  	if err != nil {
  2687  		return false, BuildErrorResponse(r, err)
  2688  	}
  2689  	defer closeBody(r)
  2690  	return CheckStatusOK(r), BuildResponse(r)
  2691  }
  2692  
  2693  // UpdateChannelMemberSchemeRoles will update the scheme-derived roles on a channel for a user.
  2694  func (c *Client4) UpdateChannelMemberSchemeRoles(channelId string, userId string, schemeRoles *SchemeRoles) (bool, *Response) {
  2695  	r, err := c.DoApiPut(c.GetChannelMemberRoute(channelId, userId)+"/schemeRoles", schemeRoles.ToJson())
  2696  	if err != nil {
  2697  		return false, BuildErrorResponse(r, err)
  2698  	}
  2699  	defer closeBody(r)
  2700  	return CheckStatusOK(r), BuildResponse(r)
  2701  }
  2702  
  2703  // UpdateChannelNotifyProps will update the notification properties on a channel for a user.
  2704  func (c *Client4) UpdateChannelNotifyProps(channelId, userId string, props map[string]string) (bool, *Response) {
  2705  	r, err := c.DoApiPut(c.GetChannelMemberRoute(channelId, userId)+"/notify_props", MapToJson(props))
  2706  	if err != nil {
  2707  		return false, BuildErrorResponse(r, err)
  2708  	}
  2709  	defer closeBody(r)
  2710  	return CheckStatusOK(r), BuildResponse(r)
  2711  }
  2712  
  2713  // AddChannelMember adds user to channel and return a channel member.
  2714  func (c *Client4) AddChannelMember(channelId, userId string) (*ChannelMember, *Response) {
  2715  	requestBody := map[string]string{"user_id": userId}
  2716  	r, err := c.DoApiPost(c.GetChannelMembersRoute(channelId)+"", MapToJson(requestBody))
  2717  	if err != nil {
  2718  		return nil, BuildErrorResponse(r, err)
  2719  	}
  2720  	defer closeBody(r)
  2721  	return ChannelMemberFromJson(r.Body), BuildResponse(r)
  2722  }
  2723  
  2724  // AddChannelMemberWithRootId adds user to channel and return a channel member. Post add to channel message has the postRootId.
  2725  func (c *Client4) AddChannelMemberWithRootId(channelId, userId, postRootId string) (*ChannelMember, *Response) {
  2726  	requestBody := map[string]string{"user_id": userId, "post_root_id": postRootId}
  2727  	r, err := c.DoApiPost(c.GetChannelMembersRoute(channelId)+"", MapToJson(requestBody))
  2728  	if err != nil {
  2729  		return nil, BuildErrorResponse(r, err)
  2730  	}
  2731  	defer closeBody(r)
  2732  	return ChannelMemberFromJson(r.Body), BuildResponse(r)
  2733  }
  2734  
  2735  // RemoveUserFromChannel will delete the channel member object for a user, effectively removing the user from a channel.
  2736  func (c *Client4) RemoveUserFromChannel(channelId, userId string) (bool, *Response) {
  2737  	r, err := c.DoApiDelete(c.GetChannelMemberRoute(channelId, userId))
  2738  	if err != nil {
  2739  		return false, BuildErrorResponse(r, err)
  2740  	}
  2741  	defer closeBody(r)
  2742  	return CheckStatusOK(r), BuildResponse(r)
  2743  }
  2744  
  2745  // AutocompleteChannelsForTeam will return an ordered list of channels autocomplete suggestions.
  2746  func (c *Client4) AutocompleteChannelsForTeam(teamId, name string) (*ChannelList, *Response) {
  2747  	query := fmt.Sprintf("?name=%v", name)
  2748  	r, err := c.DoApiGet(c.GetChannelsForTeamRoute(teamId)+"/autocomplete"+query, "")
  2749  	if err != nil {
  2750  		return nil, BuildErrorResponse(r, err)
  2751  	}
  2752  	defer closeBody(r)
  2753  	return ChannelListFromJson(r.Body), BuildResponse(r)
  2754  }
  2755  
  2756  // AutocompleteChannelsForTeamForSearch will return an ordered list of your channels autocomplete suggestions.
  2757  func (c *Client4) AutocompleteChannelsForTeamForSearch(teamId, name string) (*ChannelList, *Response) {
  2758  	query := fmt.Sprintf("?name=%v", name)
  2759  	r, err := c.DoApiGet(c.GetChannelsForTeamRoute(teamId)+"/search_autocomplete"+query, "")
  2760  	if err != nil {
  2761  		return nil, BuildErrorResponse(r, err)
  2762  	}
  2763  	defer closeBody(r)
  2764  	return ChannelListFromJson(r.Body), BuildResponse(r)
  2765  }
  2766  
  2767  // Post Section
  2768  
  2769  // CreatePost creates a post based on the provided post struct.
  2770  func (c *Client4) CreatePost(post *Post) (*Post, *Response) {
  2771  	r, err := c.DoApiPost(c.GetPostsRoute(), post.ToUnsanitizedJson())
  2772  	if err != nil {
  2773  		return nil, BuildErrorResponse(r, err)
  2774  	}
  2775  	defer closeBody(r)
  2776  	return PostFromJson(r.Body), BuildResponse(r)
  2777  }
  2778  
  2779  // CreatePostEphemeral creates a ephemeral post based on the provided post struct which is send to the given user id.
  2780  func (c *Client4) CreatePostEphemeral(post *PostEphemeral) (*Post, *Response) {
  2781  	r, err := c.DoApiPost(c.GetPostsEphemeralRoute(), post.ToUnsanitizedJson())
  2782  	if err != nil {
  2783  		return nil, BuildErrorResponse(r, err)
  2784  	}
  2785  	defer closeBody(r)
  2786  	return PostFromJson(r.Body), BuildResponse(r)
  2787  }
  2788  
  2789  // UpdatePost updates a post based on the provided post struct.
  2790  func (c *Client4) UpdatePost(postId string, post *Post) (*Post, *Response) {
  2791  	r, err := c.DoApiPut(c.GetPostRoute(postId), post.ToUnsanitizedJson())
  2792  	if err != nil {
  2793  		return nil, BuildErrorResponse(r, err)
  2794  	}
  2795  	defer closeBody(r)
  2796  	return PostFromJson(r.Body), BuildResponse(r)
  2797  }
  2798  
  2799  // PatchPost partially updates a post. Any missing fields are not updated.
  2800  func (c *Client4) PatchPost(postId string, patch *PostPatch) (*Post, *Response) {
  2801  	r, err := c.DoApiPut(c.GetPostRoute(postId)+"/patch", patch.ToJson())
  2802  	if err != nil {
  2803  		return nil, BuildErrorResponse(r, err)
  2804  	}
  2805  	defer closeBody(r)
  2806  	return PostFromJson(r.Body), BuildResponse(r)
  2807  }
  2808  
  2809  // SetPostUnread marks channel where post belongs as unread on the time of the provided post.
  2810  func (c *Client4) SetPostUnread(userId string, postId string) *Response {
  2811  	r, err := c.DoApiPost(c.GetUserRoute(userId)+c.GetPostRoute(postId)+"/set_unread", "")
  2812  	if err != nil {
  2813  		return BuildErrorResponse(r, err)
  2814  	}
  2815  	defer closeBody(r)
  2816  	return BuildResponse(r)
  2817  }
  2818  
  2819  // PinPost pin a post based on provided post id string.
  2820  func (c *Client4) PinPost(postId string) (bool, *Response) {
  2821  	r, err := c.DoApiPost(c.GetPostRoute(postId)+"/pin", "")
  2822  	if err != nil {
  2823  		return false, BuildErrorResponse(r, err)
  2824  	}
  2825  	defer closeBody(r)
  2826  	return CheckStatusOK(r), BuildResponse(r)
  2827  }
  2828  
  2829  // UnpinPost unpin a post based on provided post id string.
  2830  func (c *Client4) UnpinPost(postId string) (bool, *Response) {
  2831  	r, err := c.DoApiPost(c.GetPostRoute(postId)+"/unpin", "")
  2832  	if err != nil {
  2833  		return false, BuildErrorResponse(r, err)
  2834  	}
  2835  	defer closeBody(r)
  2836  	return CheckStatusOK(r), BuildResponse(r)
  2837  }
  2838  
  2839  // GetPost gets a single post.
  2840  func (c *Client4) GetPost(postId string, etag string) (*Post, *Response) {
  2841  	r, err := c.DoApiGet(c.GetPostRoute(postId), etag)
  2842  	if err != nil {
  2843  		return nil, BuildErrorResponse(r, err)
  2844  	}
  2845  	defer closeBody(r)
  2846  	return PostFromJson(r.Body), BuildResponse(r)
  2847  }
  2848  
  2849  // DeletePost deletes a post from the provided post id string.
  2850  func (c *Client4) DeletePost(postId string) (bool, *Response) {
  2851  	r, err := c.DoApiDelete(c.GetPostRoute(postId))
  2852  	if err != nil {
  2853  		return false, BuildErrorResponse(r, err)
  2854  	}
  2855  	defer closeBody(r)
  2856  	return CheckStatusOK(r), BuildResponse(r)
  2857  }
  2858  
  2859  // GetPostThread gets a post with all the other posts in the same thread.
  2860  func (c *Client4) GetPostThread(postId string, etag string) (*PostList, *Response) {
  2861  	r, err := c.DoApiGet(c.GetPostRoute(postId)+"/thread", etag)
  2862  	if err != nil {
  2863  		return nil, BuildErrorResponse(r, err)
  2864  	}
  2865  	defer closeBody(r)
  2866  	return PostListFromJson(r.Body), BuildResponse(r)
  2867  }
  2868  
  2869  // GetPostsForChannel gets a page of posts with an array for ordering for a channel.
  2870  func (c *Client4) GetPostsForChannel(channelId string, page, perPage int, etag string) (*PostList, *Response) {
  2871  	query := fmt.Sprintf("?page=%v&per_page=%v", page, perPage)
  2872  	r, err := c.DoApiGet(c.GetChannelRoute(channelId)+"/posts"+query, etag)
  2873  	if err != nil {
  2874  		return nil, BuildErrorResponse(r, err)
  2875  	}
  2876  	defer closeBody(r)
  2877  	return PostListFromJson(r.Body), BuildResponse(r)
  2878  }
  2879  
  2880  // GetFlaggedPostsForUser returns flagged posts of a user based on user id string.
  2881  func (c *Client4) GetFlaggedPostsForUser(userId string, page int, perPage int) (*PostList, *Response) {
  2882  	query := fmt.Sprintf("?page=%v&per_page=%v", page, perPage)
  2883  	r, err := c.DoApiGet(c.GetUserRoute(userId)+"/posts/flagged"+query, "")
  2884  	if err != nil {
  2885  		return nil, BuildErrorResponse(r, err)
  2886  	}
  2887  	defer closeBody(r)
  2888  	return PostListFromJson(r.Body), BuildResponse(r)
  2889  }
  2890  
  2891  // GetFlaggedPostsForUserInTeam returns flagged posts in team of a user based on user id string.
  2892  func (c *Client4) GetFlaggedPostsForUserInTeam(userId string, teamId string, page int, perPage int) (*PostList, *Response) {
  2893  	if !IsValidId(teamId) {
  2894  		return nil, &Response{StatusCode: http.StatusBadRequest, Error: NewAppError("GetFlaggedPostsForUserInTeam", "model.client.get_flagged_posts_in_team.missing_parameter.app_error", nil, "", http.StatusBadRequest)}
  2895  	}
  2896  
  2897  	query := fmt.Sprintf("?team_id=%v&page=%v&per_page=%v", teamId, page, perPage)
  2898  	r, err := c.DoApiGet(c.GetUserRoute(userId)+"/posts/flagged"+query, "")
  2899  	if err != nil {
  2900  		return nil, BuildErrorResponse(r, err)
  2901  	}
  2902  	defer closeBody(r)
  2903  	return PostListFromJson(r.Body), BuildResponse(r)
  2904  }
  2905  
  2906  // GetFlaggedPostsForUserInChannel returns flagged posts in channel of a user based on user id string.
  2907  func (c *Client4) GetFlaggedPostsForUserInChannel(userId string, channelId string, page int, perPage int) (*PostList, *Response) {
  2908  	if !IsValidId(channelId) {
  2909  		return nil, &Response{StatusCode: http.StatusBadRequest, Error: NewAppError("GetFlaggedPostsForUserInChannel", "model.client.get_flagged_posts_in_channel.missing_parameter.app_error", nil, "", http.StatusBadRequest)}
  2910  	}
  2911  
  2912  	query := fmt.Sprintf("?channel_id=%v&page=%v&per_page=%v", channelId, page, perPage)
  2913  	r, err := c.DoApiGet(c.GetUserRoute(userId)+"/posts/flagged"+query, "")
  2914  	if err != nil {
  2915  		return nil, BuildErrorResponse(r, err)
  2916  	}
  2917  	defer closeBody(r)
  2918  	return PostListFromJson(r.Body), BuildResponse(r)
  2919  }
  2920  
  2921  // GetPostsSince gets posts created after a specified time as Unix time in milliseconds.
  2922  func (c *Client4) GetPostsSince(channelId string, time int64) (*PostList, *Response) {
  2923  	query := fmt.Sprintf("?since=%v", time)
  2924  	r, err := c.DoApiGet(c.GetChannelRoute(channelId)+"/posts"+query, "")
  2925  	if err != nil {
  2926  		return nil, BuildErrorResponse(r, err)
  2927  	}
  2928  	defer closeBody(r)
  2929  	return PostListFromJson(r.Body), BuildResponse(r)
  2930  }
  2931  
  2932  // GetPostsAfter gets a page of posts that were posted after the post provided.
  2933  func (c *Client4) GetPostsAfter(channelId, postId string, page, perPage int, etag string) (*PostList, *Response) {
  2934  	query := fmt.Sprintf("?page=%v&per_page=%v&after=%v", page, perPage, postId)
  2935  	r, err := c.DoApiGet(c.GetChannelRoute(channelId)+"/posts"+query, etag)
  2936  	if err != nil {
  2937  		return nil, BuildErrorResponse(r, err)
  2938  	}
  2939  	defer closeBody(r)
  2940  	return PostListFromJson(r.Body), BuildResponse(r)
  2941  }
  2942  
  2943  // GetPostsBefore gets a page of posts that were posted before the post provided.
  2944  func (c *Client4) GetPostsBefore(channelId, postId string, page, perPage int, etag string) (*PostList, *Response) {
  2945  	query := fmt.Sprintf("?page=%v&per_page=%v&before=%v", page, perPage, postId)
  2946  	r, err := c.DoApiGet(c.GetChannelRoute(channelId)+"/posts"+query, etag)
  2947  	if err != nil {
  2948  		return nil, BuildErrorResponse(r, err)
  2949  	}
  2950  	defer closeBody(r)
  2951  	return PostListFromJson(r.Body), BuildResponse(r)
  2952  }
  2953  
  2954  // GetPostsAroundLastUnread gets a list of posts around last unread post by a user in a channel.
  2955  func (c *Client4) GetPostsAroundLastUnread(userId, channelId string, limitBefore, limitAfter int) (*PostList, *Response) {
  2956  	query := fmt.Sprintf("?limit_before=%v&limit_after=%v", limitBefore, limitAfter)
  2957  	if r, err := c.DoApiGet(c.GetUserRoute(userId)+c.GetChannelRoute(channelId)+"/posts/unread"+query, ""); err != nil {
  2958  		return nil, BuildErrorResponse(r, err)
  2959  	} else {
  2960  		defer closeBody(r)
  2961  		return PostListFromJson(r.Body), BuildResponse(r)
  2962  	}
  2963  }
  2964  
  2965  // SearchPosts returns any posts with matching terms string.
  2966  func (c *Client4) SearchPosts(teamId string, terms string, isOrSearch bool) (*PostList, *Response) {
  2967  	params := SearchParameter{
  2968  		Terms:      &terms,
  2969  		IsOrSearch: &isOrSearch,
  2970  	}
  2971  	return c.SearchPostsWithParams(teamId, &params)
  2972  }
  2973  
  2974  // SearchPostsWithParams returns any posts with matching terms string.
  2975  func (c *Client4) SearchPostsWithParams(teamId string, params *SearchParameter) (*PostList, *Response) {
  2976  	r, err := c.DoApiPost(c.GetTeamRoute(teamId)+"/posts/search", params.SearchParameterToJson())
  2977  	if err != nil {
  2978  		return nil, BuildErrorResponse(r, err)
  2979  	}
  2980  	defer closeBody(r)
  2981  	return PostListFromJson(r.Body), BuildResponse(r)
  2982  }
  2983  
  2984  // SearchPostsWithMatches returns any posts with matching terms string, including.
  2985  func (c *Client4) SearchPostsWithMatches(teamId string, terms string, isOrSearch bool) (*PostSearchResults, *Response) {
  2986  	requestBody := map[string]interface{}{"terms": terms, "is_or_search": isOrSearch}
  2987  	r, err := c.DoApiPost(c.GetTeamRoute(teamId)+"/posts/search", StringInterfaceToJson(requestBody))
  2988  	if err != nil {
  2989  		return nil, BuildErrorResponse(r, err)
  2990  	}
  2991  	defer closeBody(r)
  2992  	return PostSearchResultsFromJson(r.Body), BuildResponse(r)
  2993  }
  2994  
  2995  // DoPostAction performs a post action.
  2996  func (c *Client4) DoPostAction(postId, actionId string) (bool, *Response) {
  2997  	r, err := c.DoApiPost(c.GetPostRoute(postId)+"/actions/"+actionId, "")
  2998  	if err != nil {
  2999  		return false, BuildErrorResponse(r, err)
  3000  	}
  3001  	defer closeBody(r)
  3002  	return CheckStatusOK(r), BuildResponse(r)
  3003  }
  3004  
  3005  // DoPostActionWithCookie performs a post action with extra arguments
  3006  func (c *Client4) DoPostActionWithCookie(postId, actionId, selected, cookieStr string) (bool, *Response) {
  3007  	var body []byte
  3008  	if selected != "" || cookieStr != "" {
  3009  		body, _ = json.Marshal(DoPostActionRequest{
  3010  			SelectedOption: selected,
  3011  			Cookie:         cookieStr,
  3012  		})
  3013  	}
  3014  	r, err := c.DoApiPost(c.GetPostRoute(postId)+"/actions/"+actionId, string(body))
  3015  	if err != nil {
  3016  		return false, BuildErrorResponse(r, err)
  3017  	}
  3018  	defer closeBody(r)
  3019  	return CheckStatusOK(r), BuildResponse(r)
  3020  }
  3021  
  3022  // OpenInteractiveDialog sends a WebSocket event to a user's clients to
  3023  // open interactive dialogs, based on the provided trigger ID and other
  3024  // provided data. Used with interactive message buttons, menus and
  3025  // slash commands.
  3026  func (c *Client4) OpenInteractiveDialog(request OpenDialogRequest) (bool, *Response) {
  3027  	b, _ := json.Marshal(request)
  3028  	r, err := c.DoApiPost("/actions/dialogs/open", string(b))
  3029  	if err != nil {
  3030  		return false, BuildErrorResponse(r, err)
  3031  	}
  3032  	defer closeBody(r)
  3033  	return CheckStatusOK(r), BuildResponse(r)
  3034  }
  3035  
  3036  // SubmitInteractiveDialog will submit the provided dialog data to the integration
  3037  // configured by the URL. Used with the interactive dialogs integration feature.
  3038  func (c *Client4) SubmitInteractiveDialog(request SubmitDialogRequest) (*SubmitDialogResponse, *Response) {
  3039  	b, _ := json.Marshal(request)
  3040  	r, err := c.DoApiPost("/actions/dialogs/submit", string(b))
  3041  	if err != nil {
  3042  		return nil, BuildErrorResponse(r, err)
  3043  	}
  3044  	defer closeBody(r)
  3045  
  3046  	var resp SubmitDialogResponse
  3047  	json.NewDecoder(r.Body).Decode(&resp)
  3048  	return &resp, BuildResponse(r)
  3049  }
  3050  
  3051  // UploadFile will upload a file to a channel using a multipart request, to be later attached to a post.
  3052  // This method is functionally equivalent to Client4.UploadFileAsRequestBody.
  3053  func (c *Client4) UploadFile(data []byte, channelId string, filename string) (*FileUploadResponse, *Response) {
  3054  	body := &bytes.Buffer{}
  3055  	writer := multipart.NewWriter(body)
  3056  
  3057  	part, err := writer.CreateFormField("channel_id")
  3058  	if err != nil {
  3059  		return nil, &Response{Error: NewAppError("UploadPostAttachment", "model.client.upload_post_attachment.channel_id.app_error", nil, err.Error(), http.StatusBadRequest)}
  3060  	}
  3061  
  3062  	_, err = io.Copy(part, strings.NewReader(channelId))
  3063  	if err != nil {
  3064  		return nil, &Response{Error: NewAppError("UploadPostAttachment", "model.client.upload_post_attachment.channel_id.app_error", nil, err.Error(), http.StatusBadRequest)}
  3065  	}
  3066  
  3067  	part, err = writer.CreateFormFile("files", filename)
  3068  	if err != nil {
  3069  		return nil, &Response{Error: NewAppError("UploadPostAttachment", "model.client.upload_post_attachment.file.app_error", nil, err.Error(), http.StatusBadRequest)}
  3070  	}
  3071  	_, err = io.Copy(part, bytes.NewBuffer(data))
  3072  	if err != nil {
  3073  		return nil, &Response{Error: NewAppError("UploadPostAttachment", "model.client.upload_post_attachment.file.app_error", nil, err.Error(), http.StatusBadRequest)}
  3074  	}
  3075  
  3076  	err = writer.Close()
  3077  	if err != nil {
  3078  		return nil, &Response{Error: NewAppError("UploadPostAttachment", "model.client.upload_post_attachment.writer.app_error", nil, err.Error(), http.StatusBadRequest)}
  3079  	}
  3080  
  3081  	return c.DoUploadFile(c.GetFilesRoute(), body.Bytes(), writer.FormDataContentType())
  3082  }
  3083  
  3084  // UploadFileAsRequestBody will upload a file to a channel as the body of a request, to be later attached
  3085  // to a post. This method is functionally equivalent to Client4.UploadFile.
  3086  func (c *Client4) UploadFileAsRequestBody(data []byte, channelId string, filename string) (*FileUploadResponse, *Response) {
  3087  	return c.DoUploadFile(c.GetFilesRoute()+fmt.Sprintf("?channel_id=%v&filename=%v", url.QueryEscape(channelId), url.QueryEscape(filename)), data, http.DetectContentType(data))
  3088  }
  3089  
  3090  // GetFile gets the bytes for a file by id.
  3091  func (c *Client4) GetFile(fileId string) ([]byte, *Response) {
  3092  	r, appErr := c.DoApiGet(c.GetFileRoute(fileId), "")
  3093  	if appErr != nil {
  3094  		return nil, BuildErrorResponse(r, appErr)
  3095  	}
  3096  	defer closeBody(r)
  3097  
  3098  	data, err := ioutil.ReadAll(r.Body)
  3099  	if err != nil {
  3100  		return nil, BuildErrorResponse(r, NewAppError("GetFile", "model.client.read_file.app_error", nil, err.Error(), r.StatusCode))
  3101  	}
  3102  	return data, BuildResponse(r)
  3103  }
  3104  
  3105  // DownloadFile gets the bytes for a file by id, optionally adding headers to force the browser to download it.
  3106  func (c *Client4) DownloadFile(fileId string, download bool) ([]byte, *Response) {
  3107  	r, appErr := c.DoApiGet(c.GetFileRoute(fileId)+fmt.Sprintf("?download=%v", download), "")
  3108  	if appErr != nil {
  3109  		return nil, BuildErrorResponse(r, appErr)
  3110  	}
  3111  	defer closeBody(r)
  3112  
  3113  	data, err := ioutil.ReadAll(r.Body)
  3114  	if err != nil {
  3115  		return nil, BuildErrorResponse(r, NewAppError("DownloadFile", "model.client.read_file.app_error", nil, err.Error(), r.StatusCode))
  3116  	}
  3117  	return data, BuildResponse(r)
  3118  }
  3119  
  3120  // GetFileThumbnail gets the bytes for a file by id.
  3121  func (c *Client4) GetFileThumbnail(fileId string) ([]byte, *Response) {
  3122  	r, appErr := c.DoApiGet(c.GetFileRoute(fileId)+"/thumbnail", "")
  3123  	if appErr != nil {
  3124  		return nil, BuildErrorResponse(r, appErr)
  3125  	}
  3126  	defer closeBody(r)
  3127  
  3128  	data, err := ioutil.ReadAll(r.Body)
  3129  	if err != nil {
  3130  		return nil, BuildErrorResponse(r, NewAppError("GetFileThumbnail", "model.client.read_file.app_error", nil, err.Error(), r.StatusCode))
  3131  	}
  3132  	return data, BuildResponse(r)
  3133  }
  3134  
  3135  // DownloadFileThumbnail gets the bytes for a file by id, optionally adding headers to force the browser to download it.
  3136  func (c *Client4) DownloadFileThumbnail(fileId string, download bool) ([]byte, *Response) {
  3137  	r, appErr := c.DoApiGet(c.GetFileRoute(fileId)+fmt.Sprintf("/thumbnail?download=%v", download), "")
  3138  	if appErr != nil {
  3139  		return nil, BuildErrorResponse(r, appErr)
  3140  	}
  3141  	defer closeBody(r)
  3142  
  3143  	data, err := ioutil.ReadAll(r.Body)
  3144  	if err != nil {
  3145  		return nil, BuildErrorResponse(r, NewAppError("DownloadFileThumbnail", "model.client.read_file.app_error", nil, err.Error(), r.StatusCode))
  3146  	}
  3147  	return data, BuildResponse(r)
  3148  }
  3149  
  3150  // GetFileLink gets the public link of a file by id.
  3151  func (c *Client4) GetFileLink(fileId string) (string, *Response) {
  3152  	r, err := c.DoApiGet(c.GetFileRoute(fileId)+"/link", "")
  3153  	if err != nil {
  3154  		return "", BuildErrorResponse(r, err)
  3155  	}
  3156  	defer closeBody(r)
  3157  	return MapFromJson(r.Body)["link"], BuildResponse(r)
  3158  }
  3159  
  3160  // GetFilePreview gets the bytes for a file by id.
  3161  func (c *Client4) GetFilePreview(fileId string) ([]byte, *Response) {
  3162  	r, appErr := c.DoApiGet(c.GetFileRoute(fileId)+"/preview", "")
  3163  	if appErr != nil {
  3164  		return nil, BuildErrorResponse(r, appErr)
  3165  	}
  3166  	defer closeBody(r)
  3167  
  3168  	data, err := ioutil.ReadAll(r.Body)
  3169  	if err != nil {
  3170  		return nil, BuildErrorResponse(r, NewAppError("GetFilePreview", "model.client.read_file.app_error", nil, err.Error(), r.StatusCode))
  3171  	}
  3172  	return data, BuildResponse(r)
  3173  }
  3174  
  3175  // DownloadFilePreview gets the bytes for a file by id.
  3176  func (c *Client4) DownloadFilePreview(fileId string, download bool) ([]byte, *Response) {
  3177  	r, appErr := c.DoApiGet(c.GetFileRoute(fileId)+fmt.Sprintf("/preview?download=%v", download), "")
  3178  	if appErr != nil {
  3179  		return nil, BuildErrorResponse(r, appErr)
  3180  	}
  3181  	defer closeBody(r)
  3182  
  3183  	data, err := ioutil.ReadAll(r.Body)
  3184  	if err != nil {
  3185  		return nil, BuildErrorResponse(r, NewAppError("DownloadFilePreview", "model.client.read_file.app_error", nil, err.Error(), r.StatusCode))
  3186  	}
  3187  	return data, BuildResponse(r)
  3188  }
  3189  
  3190  // GetFileInfo gets all the file info objects.
  3191  func (c *Client4) GetFileInfo(fileId string) (*FileInfo, *Response) {
  3192  	r, err := c.DoApiGet(c.GetFileRoute(fileId)+"/info", "")
  3193  	if err != nil {
  3194  		return nil, BuildErrorResponse(r, err)
  3195  	}
  3196  	defer closeBody(r)
  3197  	return FileInfoFromJson(r.Body), BuildResponse(r)
  3198  }
  3199  
  3200  // GetFileInfosForPost gets all the file info objects attached to a post.
  3201  func (c *Client4) GetFileInfosForPost(postId string, etag string) ([]*FileInfo, *Response) {
  3202  	r, err := c.DoApiGet(c.GetPostRoute(postId)+"/files/info", etag)
  3203  	if err != nil {
  3204  		return nil, BuildErrorResponse(r, err)
  3205  	}
  3206  	defer closeBody(r)
  3207  	return FileInfosFromJson(r.Body), BuildResponse(r)
  3208  }
  3209  
  3210  // General/System Section
  3211  
  3212  // GetPing will return ok if the running goRoutines are below the threshold and unhealthy for above.
  3213  func (c *Client4) GetPing() (string, *Response) {
  3214  	r, err := c.DoApiGet(c.GetSystemRoute()+"/ping", "")
  3215  	if r != nil && r.StatusCode == 500 {
  3216  		defer r.Body.Close()
  3217  		return STATUS_UNHEALTHY, BuildErrorResponse(r, err)
  3218  	}
  3219  	if err != nil {
  3220  		return "", BuildErrorResponse(r, err)
  3221  	}
  3222  	defer closeBody(r)
  3223  	return MapFromJson(r.Body)["status"], BuildResponse(r)
  3224  }
  3225  
  3226  // GetPingWithServerStatus will return ok if several basic server health checks
  3227  // all pass successfully.
  3228  func (c *Client4) GetPingWithServerStatus() (string, *Response) {
  3229  	r, err := c.DoApiGet(c.GetSystemRoute()+"/ping?get_server_status="+c.boolString(true), "")
  3230  	if r != nil && r.StatusCode == 500 {
  3231  		defer r.Body.Close()
  3232  		return STATUS_UNHEALTHY, BuildErrorResponse(r, err)
  3233  	}
  3234  	if err != nil {
  3235  		return "", BuildErrorResponse(r, err)
  3236  	}
  3237  	defer closeBody(r)
  3238  	return MapFromJson(r.Body)["status"], BuildResponse(r)
  3239  }
  3240  
  3241  // TestEmail will attempt to connect to the configured SMTP server.
  3242  func (c *Client4) TestEmail(config *Config) (bool, *Response) {
  3243  	r, err := c.DoApiPost(c.GetTestEmailRoute(), config.ToJson())
  3244  	if err != nil {
  3245  		return false, BuildErrorResponse(r, err)
  3246  	}
  3247  	defer closeBody(r)
  3248  	return CheckStatusOK(r), BuildResponse(r)
  3249  }
  3250  
  3251  // TestSiteURL will test the validity of a site URL.
  3252  func (c *Client4) TestSiteURL(siteURL string) (bool, *Response) {
  3253  	requestBody := make(map[string]string)
  3254  	requestBody["site_url"] = siteURL
  3255  	r, err := c.DoApiPost(c.GetTestSiteURLRoute(), MapToJson(requestBody))
  3256  	if err != nil {
  3257  		return false, BuildErrorResponse(r, err)
  3258  	}
  3259  	defer closeBody(r)
  3260  	return CheckStatusOK(r), BuildResponse(r)
  3261  }
  3262  
  3263  // TestS3Connection will attempt to connect to the AWS S3.
  3264  func (c *Client4) TestS3Connection(config *Config) (bool, *Response) {
  3265  	r, err := c.DoApiPost(c.GetTestS3Route(), config.ToJson())
  3266  	if err != nil {
  3267  		return false, BuildErrorResponse(r, err)
  3268  	}
  3269  	defer closeBody(r)
  3270  	return CheckStatusOK(r), BuildResponse(r)
  3271  }
  3272  
  3273  // GetConfig will retrieve the server config with some sanitized items.
  3274  func (c *Client4) GetConfig() (*Config, *Response) {
  3275  	r, err := c.DoApiGet(c.GetConfigRoute(), "")
  3276  	if err != nil {
  3277  		return nil, BuildErrorResponse(r, err)
  3278  	}
  3279  	defer closeBody(r)
  3280  	return ConfigFromJson(r.Body), BuildResponse(r)
  3281  }
  3282  
  3283  // ReloadConfig will reload the server configuration.
  3284  func (c *Client4) ReloadConfig() (bool, *Response) {
  3285  	r, err := c.DoApiPost(c.GetConfigRoute()+"/reload", "")
  3286  	if err != nil {
  3287  		return false, BuildErrorResponse(r, err)
  3288  	}
  3289  	defer closeBody(r)
  3290  	return CheckStatusOK(r), BuildResponse(r)
  3291  }
  3292  
  3293  // GetOldClientConfig will retrieve the parts of the server configuration needed by the
  3294  // client, formatted in the old format.
  3295  func (c *Client4) GetOldClientConfig(etag string) (map[string]string, *Response) {
  3296  	r, err := c.DoApiGet(c.GetConfigRoute()+"/client?format=old", etag)
  3297  	if err != nil {
  3298  		return nil, BuildErrorResponse(r, err)
  3299  	}
  3300  	defer closeBody(r)
  3301  	return MapFromJson(r.Body), BuildResponse(r)
  3302  }
  3303  
  3304  // GetEnvironmentConfig will retrieve a map mirroring the server configuration where fields
  3305  // are set to true if the corresponding config setting is set through an environment variable.
  3306  // Settings that haven't been set through environment variables will be missing from the map.
  3307  func (c *Client4) GetEnvironmentConfig() (map[string]interface{}, *Response) {
  3308  	r, err := c.DoApiGet(c.GetConfigRoute()+"/environment", "")
  3309  	if err != nil {
  3310  		return nil, BuildErrorResponse(r, err)
  3311  	}
  3312  	defer closeBody(r)
  3313  	return StringInterfaceFromJson(r.Body), BuildResponse(r)
  3314  }
  3315  
  3316  // GetOldClientLicense will retrieve the parts of the server license needed by the
  3317  // client, formatted in the old format.
  3318  func (c *Client4) GetOldClientLicense(etag string) (map[string]string, *Response) {
  3319  	r, err := c.DoApiGet(c.GetLicenseRoute()+"/client?format=old", etag)
  3320  	if err != nil {
  3321  		return nil, BuildErrorResponse(r, err)
  3322  	}
  3323  	defer closeBody(r)
  3324  	return MapFromJson(r.Body), BuildResponse(r)
  3325  }
  3326  
  3327  // DatabaseRecycle will recycle the connections. Discard current connection and get new one.
  3328  func (c *Client4) DatabaseRecycle() (bool, *Response) {
  3329  	r, err := c.DoApiPost(c.GetDatabaseRoute()+"/recycle", "")
  3330  	if err != nil {
  3331  		return false, BuildErrorResponse(r, err)
  3332  	}
  3333  	defer closeBody(r)
  3334  	return CheckStatusOK(r), BuildResponse(r)
  3335  }
  3336  
  3337  // InvalidateCaches will purge the cache and can affect the performance while is cleaning.
  3338  func (c *Client4) InvalidateCaches() (bool, *Response) {
  3339  	r, err := c.DoApiPost(c.GetCacheRoute()+"/invalidate", "")
  3340  	if err != nil {
  3341  		return false, BuildErrorResponse(r, err)
  3342  	}
  3343  	defer closeBody(r)
  3344  	return CheckStatusOK(r), BuildResponse(r)
  3345  }
  3346  
  3347  // UpdateConfig will update the server configuration.
  3348  func (c *Client4) UpdateConfig(config *Config) (*Config, *Response) {
  3349  	r, err := c.DoApiPut(c.GetConfigRoute(), config.ToJson())
  3350  	if err != nil {
  3351  		return nil, BuildErrorResponse(r, err)
  3352  	}
  3353  	defer closeBody(r)
  3354  	return ConfigFromJson(r.Body), BuildResponse(r)
  3355  }
  3356  
  3357  // UploadLicenseFile will add a license file to the system.
  3358  func (c *Client4) UploadLicenseFile(data []byte) (bool, *Response) {
  3359  	body := &bytes.Buffer{}
  3360  	writer := multipart.NewWriter(body)
  3361  
  3362  	part, err := writer.CreateFormFile("license", "test-license.mattermost-license")
  3363  	if err != nil {
  3364  		return false, &Response{Error: NewAppError("UploadLicenseFile", "model.client.set_profile_user.no_file.app_error", nil, err.Error(), http.StatusBadRequest)}
  3365  	}
  3366  
  3367  	if _, err = io.Copy(part, bytes.NewBuffer(data)); err != nil {
  3368  		return false, &Response{Error: NewAppError("UploadLicenseFile", "model.client.set_profile_user.no_file.app_error", nil, err.Error(), http.StatusBadRequest)}
  3369  	}
  3370  
  3371  	if err = writer.Close(); err != nil {
  3372  		return false, &Response{Error: NewAppError("UploadLicenseFile", "model.client.set_profile_user.writer.app_error", nil, err.Error(), http.StatusBadRequest)}
  3373  	}
  3374  
  3375  	rq, err := http.NewRequest("POST", c.ApiUrl+c.GetLicenseRoute(), bytes.NewReader(body.Bytes()))
  3376  	if err != nil {
  3377  		return false, &Response{Error: NewAppError("UploadLicenseFile", "model.client.connecting.app_error", nil, err.Error(), http.StatusBadRequest)}
  3378  	}
  3379  	rq.Header.Set("Content-Type", writer.FormDataContentType())
  3380  
  3381  	if len(c.AuthToken) > 0 {
  3382  		rq.Header.Set(HEADER_AUTH, c.AuthType+" "+c.AuthToken)
  3383  	}
  3384  
  3385  	rp, err := c.HttpClient.Do(rq)
  3386  	if err != nil || rp == nil {
  3387  		return false, &Response{StatusCode: http.StatusForbidden, Error: NewAppError(c.GetLicenseRoute(), "model.client.connecting.app_error", nil, err.Error(), http.StatusForbidden)}
  3388  	}
  3389  	defer closeBody(rp)
  3390  
  3391  	if rp.StatusCode >= 300 {
  3392  		return false, BuildErrorResponse(rp, AppErrorFromJson(rp.Body))
  3393  	}
  3394  
  3395  	return CheckStatusOK(rp), BuildResponse(rp)
  3396  }
  3397  
  3398  // RemoveLicenseFile will remove the server license it exists. Note that this will
  3399  // disable all enterprise features.
  3400  func (c *Client4) RemoveLicenseFile() (bool, *Response) {
  3401  	r, err := c.DoApiDelete(c.GetLicenseRoute())
  3402  	if err != nil {
  3403  		return false, BuildErrorResponse(r, err)
  3404  	}
  3405  	defer closeBody(r)
  3406  	return CheckStatusOK(r), BuildResponse(r)
  3407  }
  3408  
  3409  // GetAnalyticsOld will retrieve analytics using the old format. New format is not
  3410  // available but the "/analytics" endpoint is reserved for it. The "name" argument is optional
  3411  // and defaults to "standard". The "teamId" argument is optional and will limit results
  3412  // to a specific team.
  3413  func (c *Client4) GetAnalyticsOld(name, teamId string) (AnalyticsRows, *Response) {
  3414  	query := fmt.Sprintf("?name=%v&team_id=%v", name, teamId)
  3415  	r, err := c.DoApiGet(c.GetAnalyticsRoute()+"/old"+query, "")
  3416  	if err != nil {
  3417  		return nil, BuildErrorResponse(r, err)
  3418  	}
  3419  	defer closeBody(r)
  3420  	return AnalyticsRowsFromJson(r.Body), BuildResponse(r)
  3421  }
  3422  
  3423  // Webhooks Section
  3424  
  3425  // CreateIncomingWebhook creates an incoming webhook for a channel.
  3426  func (c *Client4) CreateIncomingWebhook(hook *IncomingWebhook) (*IncomingWebhook, *Response) {
  3427  	r, err := c.DoApiPost(c.GetIncomingWebhooksRoute(), hook.ToJson())
  3428  	if err != nil {
  3429  		return nil, BuildErrorResponse(r, err)
  3430  	}
  3431  	defer closeBody(r)
  3432  	return IncomingWebhookFromJson(r.Body), BuildResponse(r)
  3433  }
  3434  
  3435  // UpdateIncomingWebhook updates an incoming webhook for a channel.
  3436  func (c *Client4) UpdateIncomingWebhook(hook *IncomingWebhook) (*IncomingWebhook, *Response) {
  3437  	r, err := c.DoApiPut(c.GetIncomingWebhookRoute(hook.Id), hook.ToJson())
  3438  	if err != nil {
  3439  		return nil, BuildErrorResponse(r, err)
  3440  	}
  3441  	defer closeBody(r)
  3442  	return IncomingWebhookFromJson(r.Body), BuildResponse(r)
  3443  }
  3444  
  3445  // GetIncomingWebhooks returns a page of incoming webhooks on the system. Page counting starts at 0.
  3446  func (c *Client4) GetIncomingWebhooks(page int, perPage int, etag string) ([]*IncomingWebhook, *Response) {
  3447  	query := fmt.Sprintf("?page=%v&per_page=%v", page, perPage)
  3448  	r, err := c.DoApiGet(c.GetIncomingWebhooksRoute()+query, etag)
  3449  	if err != nil {
  3450  		return nil, BuildErrorResponse(r, err)
  3451  	}
  3452  	defer closeBody(r)
  3453  	return IncomingWebhookListFromJson(r.Body), BuildResponse(r)
  3454  }
  3455  
  3456  // GetIncomingWebhooksForTeam returns a page of incoming webhooks for a team. Page counting starts at 0.
  3457  func (c *Client4) GetIncomingWebhooksForTeam(teamId string, page int, perPage int, etag string) ([]*IncomingWebhook, *Response) {
  3458  	query := fmt.Sprintf("?page=%v&per_page=%v&team_id=%v", page, perPage, teamId)
  3459  	r, err := c.DoApiGet(c.GetIncomingWebhooksRoute()+query, etag)
  3460  	if err != nil {
  3461  		return nil, BuildErrorResponse(r, err)
  3462  	}
  3463  	defer closeBody(r)
  3464  	return IncomingWebhookListFromJson(r.Body), BuildResponse(r)
  3465  }
  3466  
  3467  // GetIncomingWebhook returns an Incoming webhook given the hook ID.
  3468  func (c *Client4) GetIncomingWebhook(hookID string, etag string) (*IncomingWebhook, *Response) {
  3469  	r, err := c.DoApiGet(c.GetIncomingWebhookRoute(hookID), etag)
  3470  	if err != nil {
  3471  		return nil, BuildErrorResponse(r, err)
  3472  	}
  3473  	defer closeBody(r)
  3474  	return IncomingWebhookFromJson(r.Body), BuildResponse(r)
  3475  }
  3476  
  3477  // DeleteIncomingWebhook deletes and Incoming Webhook given the hook ID.
  3478  func (c *Client4) DeleteIncomingWebhook(hookID string) (bool, *Response) {
  3479  	r, err := c.DoApiDelete(c.GetIncomingWebhookRoute(hookID))
  3480  	if err != nil {
  3481  		return false, BuildErrorResponse(r, err)
  3482  	}
  3483  	defer closeBody(r)
  3484  	return CheckStatusOK(r), BuildResponse(r)
  3485  }
  3486  
  3487  // CreateOutgoingWebhook creates an outgoing webhook for a team or channel.
  3488  func (c *Client4) CreateOutgoingWebhook(hook *OutgoingWebhook) (*OutgoingWebhook, *Response) {
  3489  	r, err := c.DoApiPost(c.GetOutgoingWebhooksRoute(), hook.ToJson())
  3490  	if err != nil {
  3491  		return nil, BuildErrorResponse(r, err)
  3492  	}
  3493  	defer closeBody(r)
  3494  	return OutgoingWebhookFromJson(r.Body), BuildResponse(r)
  3495  }
  3496  
  3497  // UpdateOutgoingWebhook creates an outgoing webhook for a team or channel.
  3498  func (c *Client4) UpdateOutgoingWebhook(hook *OutgoingWebhook) (*OutgoingWebhook, *Response) {
  3499  	r, err := c.DoApiPut(c.GetOutgoingWebhookRoute(hook.Id), hook.ToJson())
  3500  	if err != nil {
  3501  		return nil, BuildErrorResponse(r, err)
  3502  	}
  3503  	defer closeBody(r)
  3504  	return OutgoingWebhookFromJson(r.Body), BuildResponse(r)
  3505  }
  3506  
  3507  // GetOutgoingWebhooks returns a page of outgoing webhooks on the system. Page counting starts at 0.
  3508  func (c *Client4) GetOutgoingWebhooks(page int, perPage int, etag string) ([]*OutgoingWebhook, *Response) {
  3509  	query := fmt.Sprintf("?page=%v&per_page=%v", page, perPage)
  3510  	r, err := c.DoApiGet(c.GetOutgoingWebhooksRoute()+query, etag)
  3511  	if err != nil {
  3512  		return nil, BuildErrorResponse(r, err)
  3513  	}
  3514  	defer closeBody(r)
  3515  	return OutgoingWebhookListFromJson(r.Body), BuildResponse(r)
  3516  }
  3517  
  3518  // GetOutgoingWebhook outgoing webhooks on the system requested by Hook Id.
  3519  func (c *Client4) GetOutgoingWebhook(hookId string) (*OutgoingWebhook, *Response) {
  3520  	r, err := c.DoApiGet(c.GetOutgoingWebhookRoute(hookId), "")
  3521  	if err != nil {
  3522  		return nil, BuildErrorResponse(r, err)
  3523  	}
  3524  	defer closeBody(r)
  3525  	return OutgoingWebhookFromJson(r.Body), BuildResponse(r)
  3526  }
  3527  
  3528  // GetOutgoingWebhooksForChannel returns a page of outgoing webhooks for a channel. Page counting starts at 0.
  3529  func (c *Client4) GetOutgoingWebhooksForChannel(channelId string, page int, perPage int, etag string) ([]*OutgoingWebhook, *Response) {
  3530  	query := fmt.Sprintf("?page=%v&per_page=%v&channel_id=%v", page, perPage, channelId)
  3531  	r, err := c.DoApiGet(c.GetOutgoingWebhooksRoute()+query, etag)
  3532  	if err != nil {
  3533  		return nil, BuildErrorResponse(r, err)
  3534  	}
  3535  	defer closeBody(r)
  3536  	return OutgoingWebhookListFromJson(r.Body), BuildResponse(r)
  3537  }
  3538  
  3539  // GetOutgoingWebhooksForTeam returns a page of outgoing webhooks for a team. Page counting starts at 0.
  3540  func (c *Client4) GetOutgoingWebhooksForTeam(teamId string, page int, perPage int, etag string) ([]*OutgoingWebhook, *Response) {
  3541  	query := fmt.Sprintf("?page=%v&per_page=%v&team_id=%v", page, perPage, teamId)
  3542  	r, err := c.DoApiGet(c.GetOutgoingWebhooksRoute()+query, etag)
  3543  	if err != nil {
  3544  		return nil, BuildErrorResponse(r, err)
  3545  	}
  3546  	defer closeBody(r)
  3547  	return OutgoingWebhookListFromJson(r.Body), BuildResponse(r)
  3548  }
  3549  
  3550  // RegenOutgoingHookToken regenerate the outgoing webhook token.
  3551  func (c *Client4) RegenOutgoingHookToken(hookId string) (*OutgoingWebhook, *Response) {
  3552  	r, err := c.DoApiPost(c.GetOutgoingWebhookRoute(hookId)+"/regen_token", "")
  3553  	if err != nil {
  3554  		return nil, BuildErrorResponse(r, err)
  3555  	}
  3556  	defer closeBody(r)
  3557  	return OutgoingWebhookFromJson(r.Body), BuildResponse(r)
  3558  }
  3559  
  3560  // DeleteOutgoingWebhook delete the outgoing webhook on the system requested by Hook Id.
  3561  func (c *Client4) DeleteOutgoingWebhook(hookId string) (bool, *Response) {
  3562  	r, err := c.DoApiDelete(c.GetOutgoingWebhookRoute(hookId))
  3563  	if err != nil {
  3564  		return false, BuildErrorResponse(r, err)
  3565  	}
  3566  	defer closeBody(r)
  3567  	return CheckStatusOK(r), BuildResponse(r)
  3568  }
  3569  
  3570  // Preferences Section
  3571  
  3572  // GetPreferences returns the user's preferences.
  3573  func (c *Client4) GetPreferences(userId string) (Preferences, *Response) {
  3574  	r, err := c.DoApiGet(c.GetPreferencesRoute(userId), "")
  3575  	if err != nil {
  3576  		return nil, BuildErrorResponse(r, err)
  3577  	}
  3578  	defer closeBody(r)
  3579  	preferences, _ := PreferencesFromJson(r.Body)
  3580  	return preferences, BuildResponse(r)
  3581  }
  3582  
  3583  // UpdatePreferences saves the user's preferences.
  3584  func (c *Client4) UpdatePreferences(userId string, preferences *Preferences) (bool, *Response) {
  3585  	r, err := c.DoApiPut(c.GetPreferencesRoute(userId), preferences.ToJson())
  3586  	if err != nil {
  3587  		return false, BuildErrorResponse(r, err)
  3588  	}
  3589  	defer closeBody(r)
  3590  	return true, BuildResponse(r)
  3591  }
  3592  
  3593  // DeletePreferences deletes the user's preferences.
  3594  func (c *Client4) DeletePreferences(userId string, preferences *Preferences) (bool, *Response) {
  3595  	r, err := c.DoApiPost(c.GetPreferencesRoute(userId)+"/delete", preferences.ToJson())
  3596  	if err != nil {
  3597  		return false, BuildErrorResponse(r, err)
  3598  	}
  3599  	defer closeBody(r)
  3600  	return true, BuildResponse(r)
  3601  }
  3602  
  3603  // GetPreferencesByCategory returns the user's preferences from the provided category string.
  3604  func (c *Client4) GetPreferencesByCategory(userId string, category string) (Preferences, *Response) {
  3605  	url := fmt.Sprintf(c.GetPreferencesRoute(userId)+"/%s", category)
  3606  	r, err := c.DoApiGet(url, "")
  3607  	if err != nil {
  3608  		return nil, BuildErrorResponse(r, err)
  3609  	}
  3610  	defer closeBody(r)
  3611  	preferences, _ := PreferencesFromJson(r.Body)
  3612  	return preferences, BuildResponse(r)
  3613  }
  3614  
  3615  // GetPreferenceByCategoryAndName returns the user's preferences from the provided category and preference name string.
  3616  func (c *Client4) GetPreferenceByCategoryAndName(userId string, category string, preferenceName string) (*Preference, *Response) {
  3617  	url := fmt.Sprintf(c.GetPreferencesRoute(userId)+"/%s/name/%v", category, preferenceName)
  3618  	r, err := c.DoApiGet(url, "")
  3619  	if err != nil {
  3620  		return nil, BuildErrorResponse(r, err)
  3621  	}
  3622  	defer closeBody(r)
  3623  	return PreferenceFromJson(r.Body), BuildResponse(r)
  3624  }
  3625  
  3626  // SAML Section
  3627  
  3628  // GetSamlMetadata returns metadata for the SAML configuration.
  3629  func (c *Client4) GetSamlMetadata() (string, *Response) {
  3630  	r, err := c.DoApiGet(c.GetSamlRoute()+"/metadata", "")
  3631  	if err != nil {
  3632  		return "", BuildErrorResponse(r, err)
  3633  	}
  3634  	defer closeBody(r)
  3635  	buf := new(bytes.Buffer)
  3636  	_, _ = buf.ReadFrom(r.Body)
  3637  	return buf.String(), BuildResponse(r)
  3638  }
  3639  
  3640  func samlFileToMultipart(data []byte, filename string) ([]byte, *multipart.Writer, error) {
  3641  	body := &bytes.Buffer{}
  3642  	writer := multipart.NewWriter(body)
  3643  
  3644  	part, err := writer.CreateFormFile("certificate", filename)
  3645  	if err != nil {
  3646  		return nil, nil, err
  3647  	}
  3648  
  3649  	if _, err = io.Copy(part, bytes.NewBuffer(data)); err != nil {
  3650  		return nil, nil, err
  3651  	}
  3652  
  3653  	if err := writer.Close(); err != nil {
  3654  		return nil, nil, err
  3655  	}
  3656  
  3657  	return body.Bytes(), writer, nil
  3658  }
  3659  
  3660  // UploadSamlIdpCertificate will upload an IDP certificate for SAML and set the config to use it.
  3661  // The filename parameter is deprecated and ignored: the server will pick a hard-coded filename when writing to disk.
  3662  func (c *Client4) UploadSamlIdpCertificate(data []byte, filename string) (bool, *Response) {
  3663  	body, writer, err := samlFileToMultipart(data, filename)
  3664  	if err != nil {
  3665  		return false, &Response{Error: NewAppError("UploadSamlIdpCertificate", "model.client.upload_saml_cert.app_error", nil, err.Error(), http.StatusBadRequest)}
  3666  	}
  3667  
  3668  	_, resp := c.DoUploadFile(c.GetSamlRoute()+"/certificate/idp", body, writer.FormDataContentType())
  3669  	return resp.Error == nil, resp
  3670  }
  3671  
  3672  // UploadSamlPublicCertificate will upload a public certificate for SAML and set the config to use it.
  3673  // The filename parameter is deprecated and ignored: the server will pick a hard-coded filename when writing to disk.
  3674  func (c *Client4) UploadSamlPublicCertificate(data []byte, filename string) (bool, *Response) {
  3675  	body, writer, err := samlFileToMultipart(data, filename)
  3676  	if err != nil {
  3677  		return false, &Response{Error: NewAppError("UploadSamlPublicCertificate", "model.client.upload_saml_cert.app_error", nil, err.Error(), http.StatusBadRequest)}
  3678  	}
  3679  
  3680  	_, resp := c.DoUploadFile(c.GetSamlRoute()+"/certificate/public", body, writer.FormDataContentType())
  3681  	return resp.Error == nil, resp
  3682  }
  3683  
  3684  // UploadSamlPrivateCertificate will upload a private key for SAML and set the config to use it.
  3685  // The filename parameter is deprecated and ignored: the server will pick a hard-coded filename when writing to disk.
  3686  func (c *Client4) UploadSamlPrivateCertificate(data []byte, filename string) (bool, *Response) {
  3687  	body, writer, err := samlFileToMultipart(data, filename)
  3688  	if err != nil {
  3689  		return false, &Response{Error: NewAppError("UploadSamlPrivateCertificate", "model.client.upload_saml_cert.app_error", nil, err.Error(), http.StatusBadRequest)}
  3690  	}
  3691  
  3692  	_, resp := c.DoUploadFile(c.GetSamlRoute()+"/certificate/private", body, writer.FormDataContentType())
  3693  	return resp.Error == nil, resp
  3694  }
  3695  
  3696  // DeleteSamlIdpCertificate deletes the SAML IDP certificate from the server and updates the config to not use it and disable SAML.
  3697  func (c *Client4) DeleteSamlIdpCertificate() (bool, *Response) {
  3698  	r, err := c.DoApiDelete(c.GetSamlRoute() + "/certificate/idp")
  3699  	if err != nil {
  3700  		return false, BuildErrorResponse(r, err)
  3701  	}
  3702  	defer closeBody(r)
  3703  	return CheckStatusOK(r), BuildResponse(r)
  3704  }
  3705  
  3706  // DeleteSamlPublicCertificate deletes the SAML IDP certificate from the server and updates the config to not use it and disable SAML.
  3707  func (c *Client4) DeleteSamlPublicCertificate() (bool, *Response) {
  3708  	r, err := c.DoApiDelete(c.GetSamlRoute() + "/certificate/public")
  3709  	if err != nil {
  3710  		return false, BuildErrorResponse(r, err)
  3711  	}
  3712  	defer closeBody(r)
  3713  	return CheckStatusOK(r), BuildResponse(r)
  3714  }
  3715  
  3716  // DeleteSamlPrivateCertificate deletes the SAML IDP certificate from the server and updates the config to not use it and disable SAML.
  3717  func (c *Client4) DeleteSamlPrivateCertificate() (bool, *Response) {
  3718  	r, err := c.DoApiDelete(c.GetSamlRoute() + "/certificate/private")
  3719  	if err != nil {
  3720  		return false, BuildErrorResponse(r, err)
  3721  	}
  3722  	defer closeBody(r)
  3723  	return CheckStatusOK(r), BuildResponse(r)
  3724  }
  3725  
  3726  // GetSamlCertificateStatus returns metadata for the SAML configuration.
  3727  func (c *Client4) GetSamlCertificateStatus() (*SamlCertificateStatus, *Response) {
  3728  	r, err := c.DoApiGet(c.GetSamlRoute()+"/certificate/status", "")
  3729  	if err != nil {
  3730  		return nil, BuildErrorResponse(r, err)
  3731  	}
  3732  	defer closeBody(r)
  3733  	return SamlCertificateStatusFromJson(r.Body), BuildResponse(r)
  3734  }
  3735  
  3736  func (c *Client4) GetSamlMetadataFromIdp(samlMetadataURL string) (*SamlMetadataResponse, *Response) {
  3737  	requestBody := make(map[string]string)
  3738  	requestBody["saml_metadata_url"] = samlMetadataURL
  3739  	r, err := c.DoApiPost(c.GetSamlRoute()+"/metadatafromidp", MapToJson(requestBody))
  3740  	if err != nil {
  3741  		return nil, BuildErrorResponse(r, err)
  3742  	}
  3743  
  3744  	defer closeBody(r)
  3745  	return SamlMetadataResponseFromJson(r.Body), BuildResponse(r)
  3746  }
  3747  
  3748  // Compliance Section
  3749  
  3750  // CreateComplianceReport creates an incoming webhook for a channel.
  3751  func (c *Client4) CreateComplianceReport(report *Compliance) (*Compliance, *Response) {
  3752  	r, err := c.DoApiPost(c.GetComplianceReportsRoute(), report.ToJson())
  3753  	if err != nil {
  3754  		return nil, BuildErrorResponse(r, err)
  3755  	}
  3756  	defer closeBody(r)
  3757  	return ComplianceFromJson(r.Body), BuildResponse(r)
  3758  }
  3759  
  3760  // GetComplianceReports returns list of compliance reports.
  3761  func (c *Client4) GetComplianceReports(page, perPage int) (Compliances, *Response) {
  3762  	query := fmt.Sprintf("?page=%v&per_page=%v", page, perPage)
  3763  	r, err := c.DoApiGet(c.GetComplianceReportsRoute()+query, "")
  3764  	if err != nil {
  3765  		return nil, BuildErrorResponse(r, err)
  3766  	}
  3767  	defer closeBody(r)
  3768  	return CompliancesFromJson(r.Body), BuildResponse(r)
  3769  }
  3770  
  3771  // GetComplianceReport returns a compliance report.
  3772  func (c *Client4) GetComplianceReport(reportId string) (*Compliance, *Response) {
  3773  	r, err := c.DoApiGet(c.GetComplianceReportRoute(reportId), "")
  3774  	if err != nil {
  3775  		return nil, BuildErrorResponse(r, err)
  3776  	}
  3777  	defer closeBody(r)
  3778  	return ComplianceFromJson(r.Body), BuildResponse(r)
  3779  }
  3780  
  3781  // DownloadComplianceReport returns a full compliance report as a file.
  3782  func (c *Client4) DownloadComplianceReport(reportId string) ([]byte, *Response) {
  3783  	rq, err := http.NewRequest("GET", c.ApiUrl+c.GetComplianceReportRoute(reportId), nil)
  3784  	if err != nil {
  3785  		return nil, &Response{Error: NewAppError("DownloadComplianceReport", "model.client.connecting.app_error", nil, err.Error(), http.StatusBadRequest)}
  3786  	}
  3787  
  3788  	if len(c.AuthToken) > 0 {
  3789  		rq.Header.Set(HEADER_AUTH, "BEARER "+c.AuthToken)
  3790  	}
  3791  
  3792  	rp, err := c.HttpClient.Do(rq)
  3793  	if err != nil || rp == nil {
  3794  		return nil, &Response{Error: NewAppError("DownloadComplianceReport", "model.client.connecting.app_error", nil, err.Error(), http.StatusBadRequest)}
  3795  	}
  3796  	defer closeBody(rp)
  3797  
  3798  	if rp.StatusCode >= 300 {
  3799  		return nil, BuildErrorResponse(rp, AppErrorFromJson(rp.Body))
  3800  	}
  3801  
  3802  	data, err := ioutil.ReadAll(rp.Body)
  3803  	if err != nil {
  3804  		return nil, BuildErrorResponse(rp, NewAppError("DownloadComplianceReport", "model.client.read_file.app_error", nil, err.Error(), rp.StatusCode))
  3805  	}
  3806  
  3807  	return data, BuildResponse(rp)
  3808  }
  3809  
  3810  // Cluster Section
  3811  
  3812  // GetClusterStatus returns the status of all the configured cluster nodes.
  3813  func (c *Client4) GetClusterStatus() ([]*ClusterInfo, *Response) {
  3814  	r, err := c.DoApiGet(c.GetClusterRoute()+"/status", "")
  3815  	if err != nil {
  3816  		return nil, BuildErrorResponse(r, err)
  3817  	}
  3818  	defer closeBody(r)
  3819  	return ClusterInfosFromJson(r.Body), BuildResponse(r)
  3820  }
  3821  
  3822  // LDAP Section
  3823  
  3824  // SyncLdap will force a sync with the configured LDAP server.
  3825  func (c *Client4) SyncLdap() (bool, *Response) {
  3826  	r, err := c.DoApiPost(c.GetLdapRoute()+"/sync", "")
  3827  	if err != nil {
  3828  		return false, BuildErrorResponse(r, err)
  3829  	}
  3830  	defer closeBody(r)
  3831  	return CheckStatusOK(r), BuildResponse(r)
  3832  }
  3833  
  3834  // TestLdap will attempt to connect to the configured LDAP server and return OK if configured
  3835  // correctly.
  3836  func (c *Client4) TestLdap() (bool, *Response) {
  3837  	r, err := c.DoApiPost(c.GetLdapRoute()+"/test", "")
  3838  	if err != nil {
  3839  		return false, BuildErrorResponse(r, err)
  3840  	}
  3841  	defer closeBody(r)
  3842  	return CheckStatusOK(r), BuildResponse(r)
  3843  }
  3844  
  3845  // GetLdapGroups retrieves the immediate child groups of the given parent group.
  3846  func (c *Client4) GetLdapGroups() ([]*Group, *Response) {
  3847  	path := fmt.Sprintf("%s/groups", c.GetLdapRoute())
  3848  
  3849  	r, appErr := c.DoApiGet(path, "")
  3850  	if appErr != nil {
  3851  		return nil, BuildErrorResponse(r, appErr)
  3852  	}
  3853  	defer closeBody(r)
  3854  
  3855  	return GroupsFromJson(r.Body), BuildResponse(r)
  3856  }
  3857  
  3858  // LinkLdapGroup creates or undeletes a Mattermost group and associates it to the given LDAP group DN.
  3859  func (c *Client4) LinkLdapGroup(dn string) (*Group, *Response) {
  3860  	path := fmt.Sprintf("%s/groups/%s/link", c.GetLdapRoute(), dn)
  3861  
  3862  	r, appErr := c.DoApiPost(path, "")
  3863  	if appErr != nil {
  3864  		return nil, BuildErrorResponse(r, appErr)
  3865  	}
  3866  	defer closeBody(r)
  3867  
  3868  	return GroupFromJson(r.Body), BuildResponse(r)
  3869  }
  3870  
  3871  // UnlinkLdapGroup deletes the Mattermost group associated with the given LDAP group DN.
  3872  func (c *Client4) UnlinkLdapGroup(dn string) (*Group, *Response) {
  3873  	path := fmt.Sprintf("%s/groups/%s/link", c.GetLdapRoute(), dn)
  3874  
  3875  	r, appErr := c.DoApiDelete(path)
  3876  	if appErr != nil {
  3877  		return nil, BuildErrorResponse(r, appErr)
  3878  	}
  3879  	defer closeBody(r)
  3880  
  3881  	return GroupFromJson(r.Body), BuildResponse(r)
  3882  }
  3883  
  3884  // MigrateIdLdap migrates the LDAP enabled users to given attribute
  3885  func (c *Client4) MigrateIdLdap(toAttribute string) (bool, *Response) {
  3886  	r, err := c.DoApiPost(c.GetLdapRoute()+"/migrateid", MapToJson(map[string]string{
  3887  		"toAttribute": toAttribute,
  3888  	}))
  3889  	if err != nil {
  3890  		return false, BuildErrorResponse(r, err)
  3891  	}
  3892  	defer closeBody(r)
  3893  	return CheckStatusOK(r), BuildResponse(r)
  3894  }
  3895  
  3896  // GetGroupsByChannel retrieves the Mattermost Groups associated with a given channel
  3897  func (c *Client4) GetGroupsByChannel(channelId string, opts GroupSearchOpts) ([]*GroupWithSchemeAdmin, int, *Response) {
  3898  	path := fmt.Sprintf("%s/groups?q=%v&include_member_count=%v&filter_allow_reference=%v", c.GetChannelRoute(channelId), opts.Q, opts.IncludeMemberCount, opts.FilterAllowReference)
  3899  	if opts.PageOpts != nil {
  3900  		path = fmt.Sprintf("%s&page=%v&per_page=%v", path, opts.PageOpts.Page, opts.PageOpts.PerPage)
  3901  	}
  3902  	r, appErr := c.DoApiGet(path, "")
  3903  	if appErr != nil {
  3904  		return nil, 0, BuildErrorResponse(r, appErr)
  3905  	}
  3906  	defer closeBody(r)
  3907  
  3908  	responseData := struct {
  3909  		Groups []*GroupWithSchemeAdmin `json:"groups"`
  3910  		Count  int                     `json:"total_group_count"`
  3911  	}{}
  3912  	if err := json.NewDecoder(r.Body).Decode(&responseData); err != nil {
  3913  		appErr := NewAppError("Api4.GetGroupsByChannel", "api.marshal_error", nil, err.Error(), http.StatusInternalServerError)
  3914  		return nil, 0, BuildErrorResponse(r, appErr)
  3915  	}
  3916  
  3917  	return responseData.Groups, responseData.Count, BuildResponse(r)
  3918  }
  3919  
  3920  // GetGroupsByTeam retrieves the Mattermost Groups associated with a given team
  3921  func (c *Client4) GetGroupsByTeam(teamId string, opts GroupSearchOpts) ([]*GroupWithSchemeAdmin, int, *Response) {
  3922  	path := fmt.Sprintf("%s/groups?q=%v&include_member_count=%v&filter_allow_reference=%v", c.GetTeamRoute(teamId), opts.Q, opts.IncludeMemberCount, opts.FilterAllowReference)
  3923  	if opts.PageOpts != nil {
  3924  		path = fmt.Sprintf("%s&page=%v&per_page=%v", path, opts.PageOpts.Page, opts.PageOpts.PerPage)
  3925  	}
  3926  	r, appErr := c.DoApiGet(path, "")
  3927  	if appErr != nil {
  3928  		return nil, 0, BuildErrorResponse(r, appErr)
  3929  	}
  3930  	defer closeBody(r)
  3931  
  3932  	responseData := struct {
  3933  		Groups []*GroupWithSchemeAdmin `json:"groups"`
  3934  		Count  int                     `json:"total_group_count"`
  3935  	}{}
  3936  	if err := json.NewDecoder(r.Body).Decode(&responseData); err != nil {
  3937  		appErr := NewAppError("Api4.GetGroupsByTeam", "api.marshal_error", nil, err.Error(), http.StatusInternalServerError)
  3938  		return nil, 0, BuildErrorResponse(r, appErr)
  3939  	}
  3940  
  3941  	return responseData.Groups, responseData.Count, BuildResponse(r)
  3942  }
  3943  
  3944  // GetGroupsAssociatedToChannelsByTeam retrieves the Mattermost Groups associated with channels in a given team
  3945  func (c *Client4) GetGroupsAssociatedToChannelsByTeam(teamId string, opts GroupSearchOpts) (map[string][]*GroupWithSchemeAdmin, *Response) {
  3946  	path := fmt.Sprintf("%s/groups_by_channels?q=%v&filter_allow_reference=%v", c.GetTeamRoute(teamId), opts.Q, opts.FilterAllowReference)
  3947  	if opts.PageOpts != nil {
  3948  		path = fmt.Sprintf("%s&page=%v&per_page=%v", path, opts.PageOpts.Page, opts.PageOpts.PerPage)
  3949  	}
  3950  	r, appErr := c.DoApiGet(path, "")
  3951  	if appErr != nil {
  3952  		return nil, BuildErrorResponse(r, appErr)
  3953  	}
  3954  	defer closeBody(r)
  3955  
  3956  	responseData := struct {
  3957  		GroupsAssociatedToChannels map[string][]*GroupWithSchemeAdmin `json:"groups"`
  3958  	}{}
  3959  	if err := json.NewDecoder(r.Body).Decode(&responseData); err != nil {
  3960  		appErr := NewAppError("Api4.GetGroupsAssociatedToChannelsByTeam", "api.marshal_error", nil, err.Error(), http.StatusInternalServerError)
  3961  		return nil, BuildErrorResponse(r, appErr)
  3962  	}
  3963  
  3964  	return responseData.GroupsAssociatedToChannels, BuildResponse(r)
  3965  }
  3966  
  3967  // GetGroups retrieves Mattermost Groups
  3968  func (c *Client4) GetGroups(opts GroupSearchOpts) ([]*Group, *Response) {
  3969  	path := fmt.Sprintf(
  3970  		"%s?include_member_count=%v&not_associated_to_team=%v&not_associated_to_channel=%v&filter_allow_reference=%v&q=%v&filter_parent_team_permitted=%v",
  3971  		c.GetGroupsRoute(),
  3972  		opts.IncludeMemberCount,
  3973  		opts.NotAssociatedToTeam,
  3974  		opts.NotAssociatedToChannel,
  3975  		opts.FilterAllowReference,
  3976  		opts.Q,
  3977  		opts.FilterParentTeamPermitted,
  3978  	)
  3979  	if opts.Since > 0 {
  3980  		path = fmt.Sprintf("%s&since=%v", path, opts.Since)
  3981  	}
  3982  	if opts.PageOpts != nil {
  3983  		path = fmt.Sprintf("%s&page=%v&per_page=%v", path, opts.PageOpts.Page, opts.PageOpts.PerPage)
  3984  	}
  3985  	r, appErr := c.DoApiGet(path, "")
  3986  	if appErr != nil {
  3987  		return nil, BuildErrorResponse(r, appErr)
  3988  	}
  3989  	defer closeBody(r)
  3990  
  3991  	return GroupsFromJson(r.Body), BuildResponse(r)
  3992  }
  3993  
  3994  // GetGroupsByUserId retrieves Mattermost Groups for a user
  3995  func (c *Client4) GetGroupsByUserId(userId string) ([]*Group, *Response) {
  3996  	path := fmt.Sprintf(
  3997  		"%s/%v/groups",
  3998  		c.GetUsersRoute(),
  3999  		userId,
  4000  	)
  4001  
  4002  	r, appErr := c.DoApiGet(path, "")
  4003  	if appErr != nil {
  4004  		return nil, BuildErrorResponse(r, appErr)
  4005  	}
  4006  	defer closeBody(r)
  4007  	return GroupsFromJson(r.Body), BuildResponse(r)
  4008  }
  4009  
  4010  // Audits Section
  4011  
  4012  // GetAudits returns a list of audits for the whole system.
  4013  func (c *Client4) GetAudits(page int, perPage int, etag string) (Audits, *Response) {
  4014  	query := fmt.Sprintf("?page=%v&per_page=%v", page, perPage)
  4015  	r, err := c.DoApiGet("/audits"+query, etag)
  4016  	if err != nil {
  4017  		return nil, BuildErrorResponse(r, err)
  4018  	}
  4019  	defer closeBody(r)
  4020  	return AuditsFromJson(r.Body), BuildResponse(r)
  4021  }
  4022  
  4023  // Brand Section
  4024  
  4025  // GetBrandImage retrieves the previously uploaded brand image.
  4026  func (c *Client4) GetBrandImage() ([]byte, *Response) {
  4027  	r, appErr := c.DoApiGet(c.GetBrandRoute()+"/image", "")
  4028  	if appErr != nil {
  4029  		return nil, BuildErrorResponse(r, appErr)
  4030  	}
  4031  	defer closeBody(r)
  4032  
  4033  	if r.StatusCode >= 300 {
  4034  		return nil, BuildErrorResponse(r, AppErrorFromJson(r.Body))
  4035  	}
  4036  
  4037  	data, err := ioutil.ReadAll(r.Body)
  4038  	if err != nil {
  4039  		return nil, BuildErrorResponse(r, NewAppError("GetBrandImage", "model.client.read_file.app_error", nil, err.Error(), r.StatusCode))
  4040  	}
  4041  
  4042  	return data, BuildResponse(r)
  4043  }
  4044  
  4045  // DeleteBrandImage deletes the brand image for the system.
  4046  func (c *Client4) DeleteBrandImage() *Response {
  4047  	r, err := c.DoApiDelete(c.GetBrandRoute() + "/image")
  4048  	if err != nil {
  4049  		return BuildErrorResponse(r, err)
  4050  	}
  4051  	return BuildResponse(r)
  4052  }
  4053  
  4054  // UploadBrandImage sets the brand image for the system.
  4055  func (c *Client4) UploadBrandImage(data []byte) (bool, *Response) {
  4056  	body := &bytes.Buffer{}
  4057  	writer := multipart.NewWriter(body)
  4058  
  4059  	part, err := writer.CreateFormFile("image", "brand.png")
  4060  	if err != nil {
  4061  		return false, &Response{Error: NewAppError("UploadBrandImage", "model.client.set_profile_user.no_file.app_error", nil, err.Error(), http.StatusBadRequest)}
  4062  	}
  4063  
  4064  	if _, err = io.Copy(part, bytes.NewBuffer(data)); err != nil {
  4065  		return false, &Response{Error: NewAppError("UploadBrandImage", "model.client.set_profile_user.no_file.app_error", nil, err.Error(), http.StatusBadRequest)}
  4066  	}
  4067  
  4068  	if err = writer.Close(); err != nil {
  4069  		return false, &Response{Error: NewAppError("UploadBrandImage", "model.client.set_profile_user.writer.app_error", nil, err.Error(), http.StatusBadRequest)}
  4070  	}
  4071  
  4072  	rq, err := http.NewRequest("POST", c.ApiUrl+c.GetBrandRoute()+"/image", bytes.NewReader(body.Bytes()))
  4073  	if err != nil {
  4074  		return false, &Response{Error: NewAppError("UploadBrandImage", "model.client.connecting.app_error", nil, err.Error(), http.StatusBadRequest)}
  4075  	}
  4076  	rq.Header.Set("Content-Type", writer.FormDataContentType())
  4077  
  4078  	if len(c.AuthToken) > 0 {
  4079  		rq.Header.Set(HEADER_AUTH, c.AuthType+" "+c.AuthToken)
  4080  	}
  4081  
  4082  	rp, err := c.HttpClient.Do(rq)
  4083  	if err != nil || rp == nil {
  4084  		return false, &Response{StatusCode: http.StatusForbidden, Error: NewAppError(c.GetBrandRoute()+"/image", "model.client.connecting.app_error", nil, err.Error(), http.StatusForbidden)}
  4085  	}
  4086  	defer closeBody(rp)
  4087  
  4088  	if rp.StatusCode >= 300 {
  4089  		return false, BuildErrorResponse(rp, AppErrorFromJson(rp.Body))
  4090  	}
  4091  
  4092  	return CheckStatusOK(rp), BuildResponse(rp)
  4093  }
  4094  
  4095  // Logs Section
  4096  
  4097  // GetLogs page of logs as a string array.
  4098  func (c *Client4) GetLogs(page, perPage int) ([]string, *Response) {
  4099  	query := fmt.Sprintf("?page=%v&logs_per_page=%v", page, perPage)
  4100  	r, err := c.DoApiGet("/logs"+query, "")
  4101  	if err != nil {
  4102  		return nil, BuildErrorResponse(r, err)
  4103  	}
  4104  	defer closeBody(r)
  4105  	return ArrayFromJson(r.Body), BuildResponse(r)
  4106  }
  4107  
  4108  // PostLog is a convenience Web Service call so clients can log messages into
  4109  // the server-side logs. For example we typically log javascript error messages
  4110  // into the server-side. It returns the log message if the logging was successful.
  4111  func (c *Client4) PostLog(message map[string]string) (map[string]string, *Response) {
  4112  	r, err := c.DoApiPost("/logs", MapToJson(message))
  4113  	if err != nil {
  4114  		return nil, BuildErrorResponse(r, err)
  4115  	}
  4116  	defer closeBody(r)
  4117  	return MapFromJson(r.Body), BuildResponse(r)
  4118  }
  4119  
  4120  // OAuth Section
  4121  
  4122  // CreateOAuthApp will register a new OAuth 2.0 client application with Mattermost acting as an OAuth 2.0 service provider.
  4123  func (c *Client4) CreateOAuthApp(app *OAuthApp) (*OAuthApp, *Response) {
  4124  	r, err := c.DoApiPost(c.GetOAuthAppsRoute(), app.ToJson())
  4125  	if err != nil {
  4126  		return nil, BuildErrorResponse(r, err)
  4127  	}
  4128  	defer closeBody(r)
  4129  	return OAuthAppFromJson(r.Body), BuildResponse(r)
  4130  }
  4131  
  4132  // UpdateOAuthApp updates a page of registered OAuth 2.0 client applications with Mattermost acting as an OAuth 2.0 service provider.
  4133  func (c *Client4) UpdateOAuthApp(app *OAuthApp) (*OAuthApp, *Response) {
  4134  	r, err := c.DoApiPut(c.GetOAuthAppRoute(app.Id), app.ToJson())
  4135  	if err != nil {
  4136  		return nil, BuildErrorResponse(r, err)
  4137  	}
  4138  	defer closeBody(r)
  4139  	return OAuthAppFromJson(r.Body), BuildResponse(r)
  4140  }
  4141  
  4142  // GetOAuthApps gets a page of registered OAuth 2.0 client applications with Mattermost acting as an OAuth 2.0 service provider.
  4143  func (c *Client4) GetOAuthApps(page, perPage int) ([]*OAuthApp, *Response) {
  4144  	query := fmt.Sprintf("?page=%v&per_page=%v", page, perPage)
  4145  	r, err := c.DoApiGet(c.GetOAuthAppsRoute()+query, "")
  4146  	if err != nil {
  4147  		return nil, BuildErrorResponse(r, err)
  4148  	}
  4149  	defer closeBody(r)
  4150  	return OAuthAppListFromJson(r.Body), BuildResponse(r)
  4151  }
  4152  
  4153  // GetOAuthApp gets a registered OAuth 2.0 client application with Mattermost acting as an OAuth 2.0 service provider.
  4154  func (c *Client4) GetOAuthApp(appId string) (*OAuthApp, *Response) {
  4155  	r, err := c.DoApiGet(c.GetOAuthAppRoute(appId), "")
  4156  	if err != nil {
  4157  		return nil, BuildErrorResponse(r, err)
  4158  	}
  4159  	defer closeBody(r)
  4160  	return OAuthAppFromJson(r.Body), BuildResponse(r)
  4161  }
  4162  
  4163  // GetOAuthAppInfo gets a sanitized version of a registered OAuth 2.0 client application with Mattermost acting as an OAuth 2.0 service provider.
  4164  func (c *Client4) GetOAuthAppInfo(appId string) (*OAuthApp, *Response) {
  4165  	r, err := c.DoApiGet(c.GetOAuthAppRoute(appId)+"/info", "")
  4166  	if err != nil {
  4167  		return nil, BuildErrorResponse(r, err)
  4168  	}
  4169  	defer closeBody(r)
  4170  	return OAuthAppFromJson(r.Body), BuildResponse(r)
  4171  }
  4172  
  4173  // DeleteOAuthApp deletes a registered OAuth 2.0 client application.
  4174  func (c *Client4) DeleteOAuthApp(appId string) (bool, *Response) {
  4175  	r, err := c.DoApiDelete(c.GetOAuthAppRoute(appId))
  4176  	if err != nil {
  4177  		return false, BuildErrorResponse(r, err)
  4178  	}
  4179  	defer closeBody(r)
  4180  	return CheckStatusOK(r), BuildResponse(r)
  4181  }
  4182  
  4183  // RegenerateOAuthAppSecret regenerates the client secret for a registered OAuth 2.0 client application.
  4184  func (c *Client4) RegenerateOAuthAppSecret(appId string) (*OAuthApp, *Response) {
  4185  	r, err := c.DoApiPost(c.GetOAuthAppRoute(appId)+"/regen_secret", "")
  4186  	if err != nil {
  4187  		return nil, BuildErrorResponse(r, err)
  4188  	}
  4189  	defer closeBody(r)
  4190  	return OAuthAppFromJson(r.Body), BuildResponse(r)
  4191  }
  4192  
  4193  // GetAuthorizedOAuthAppsForUser gets a page of OAuth 2.0 client applications the user has authorized to use access their account.
  4194  func (c *Client4) GetAuthorizedOAuthAppsForUser(userId string, page, perPage int) ([]*OAuthApp, *Response) {
  4195  	query := fmt.Sprintf("?page=%v&per_page=%v", page, perPage)
  4196  	r, err := c.DoApiGet(c.GetUserRoute(userId)+"/oauth/apps/authorized"+query, "")
  4197  	if err != nil {
  4198  		return nil, BuildErrorResponse(r, err)
  4199  	}
  4200  	defer closeBody(r)
  4201  	return OAuthAppListFromJson(r.Body), BuildResponse(r)
  4202  }
  4203  
  4204  // AuthorizeOAuthApp will authorize an OAuth 2.0 client application to access a user's account and provide a redirect link to follow.
  4205  func (c *Client4) AuthorizeOAuthApp(authRequest *AuthorizeRequest) (string, *Response) {
  4206  	r, err := c.DoApiRequest(http.MethodPost, c.Url+"/oauth/authorize", authRequest.ToJson(), "")
  4207  	if err != nil {
  4208  		return "", BuildErrorResponse(r, err)
  4209  	}
  4210  	defer closeBody(r)
  4211  	return MapFromJson(r.Body)["redirect"], BuildResponse(r)
  4212  }
  4213  
  4214  // DeauthorizeOAuthApp will deauthorize an OAuth 2.0 client application from accessing a user's account.
  4215  func (c *Client4) DeauthorizeOAuthApp(appId string) (bool, *Response) {
  4216  	requestData := map[string]string{"client_id": appId}
  4217  	r, err := c.DoApiRequest(http.MethodPost, c.Url+"/oauth/deauthorize", MapToJson(requestData), "")
  4218  	if err != nil {
  4219  		return false, BuildErrorResponse(r, err)
  4220  	}
  4221  	defer closeBody(r)
  4222  	return CheckStatusOK(r), BuildResponse(r)
  4223  }
  4224  
  4225  // GetOAuthAccessToken is a test helper function for the OAuth access token endpoint.
  4226  func (c *Client4) GetOAuthAccessToken(data url.Values) (*AccessResponse, *Response) {
  4227  	rq, err := http.NewRequest(http.MethodPost, c.Url+"/oauth/access_token", strings.NewReader(data.Encode()))
  4228  	if err != nil {
  4229  		return nil, &Response{Error: NewAppError(c.Url+"/oauth/access_token", "model.client.connecting.app_error", nil, err.Error(), http.StatusBadRequest)}
  4230  	}
  4231  	rq.Header.Set("Content-Type", "application/x-www-form-urlencoded")
  4232  
  4233  	if len(c.AuthToken) > 0 {
  4234  		rq.Header.Set(HEADER_AUTH, c.AuthType+" "+c.AuthToken)
  4235  	}
  4236  
  4237  	rp, err := c.HttpClient.Do(rq)
  4238  	if err != nil || rp == nil {
  4239  		return nil, &Response{StatusCode: http.StatusForbidden, Error: NewAppError(c.Url+"/oauth/access_token", "model.client.connecting.app_error", nil, err.Error(), 403)}
  4240  	}
  4241  	defer closeBody(rp)
  4242  
  4243  	if rp.StatusCode >= 300 {
  4244  		return nil, BuildErrorResponse(rp, AppErrorFromJson(rp.Body))
  4245  	}
  4246  
  4247  	return AccessResponseFromJson(rp.Body), BuildResponse(rp)
  4248  }
  4249  
  4250  // Elasticsearch Section
  4251  
  4252  // TestElasticsearch will attempt to connect to the configured Elasticsearch server and return OK if configured.
  4253  // correctly.
  4254  func (c *Client4) TestElasticsearch() (bool, *Response) {
  4255  	r, err := c.DoApiPost(c.GetElasticsearchRoute()+"/test", "")
  4256  	if err != nil {
  4257  		return false, BuildErrorResponse(r, err)
  4258  	}
  4259  	defer closeBody(r)
  4260  	return CheckStatusOK(r), BuildResponse(r)
  4261  }
  4262  
  4263  // PurgeElasticsearchIndexes immediately deletes all Elasticsearch indexes.
  4264  func (c *Client4) PurgeElasticsearchIndexes() (bool, *Response) {
  4265  	r, err := c.DoApiPost(c.GetElasticsearchRoute()+"/purge_indexes", "")
  4266  	if err != nil {
  4267  		return false, BuildErrorResponse(r, err)
  4268  	}
  4269  	defer closeBody(r)
  4270  	return CheckStatusOK(r), BuildResponse(r)
  4271  }
  4272  
  4273  // Bleve Section
  4274  
  4275  // PurgeBleveIndexes immediately deletes all Bleve indexes.
  4276  func (c *Client4) PurgeBleveIndexes() (bool, *Response) {
  4277  	r, err := c.DoApiPost(c.GetBleveRoute()+"/purge_indexes", "")
  4278  	if err != nil {
  4279  		return false, BuildErrorResponse(r, err)
  4280  	}
  4281  	defer closeBody(r)
  4282  	return CheckStatusOK(r), BuildResponse(r)
  4283  }
  4284  
  4285  // Data Retention Section
  4286  
  4287  // GetDataRetentionPolicy will get the current server data retention policy details.
  4288  func (c *Client4) GetDataRetentionPolicy() (*DataRetentionPolicy, *Response) {
  4289  	r, err := c.DoApiGet(c.GetDataRetentionRoute()+"/policy", "")
  4290  	if err != nil {
  4291  		return nil, BuildErrorResponse(r, err)
  4292  	}
  4293  	defer closeBody(r)
  4294  	return DataRetentionPolicyFromJson(r.Body), BuildResponse(r)
  4295  }
  4296  
  4297  // Commands Section
  4298  
  4299  // CreateCommand will create a new command if the user have the right permissions.
  4300  func (c *Client4) CreateCommand(cmd *Command) (*Command, *Response) {
  4301  	r, err := c.DoApiPost(c.GetCommandsRoute(), cmd.ToJson())
  4302  	if err != nil {
  4303  		return nil, BuildErrorResponse(r, err)
  4304  	}
  4305  	defer closeBody(r)
  4306  	return CommandFromJson(r.Body), BuildResponse(r)
  4307  }
  4308  
  4309  // UpdateCommand updates a command based on the provided Command struct.
  4310  func (c *Client4) UpdateCommand(cmd *Command) (*Command, *Response) {
  4311  	r, err := c.DoApiPut(c.GetCommandRoute(cmd.Id), cmd.ToJson())
  4312  	if err != nil {
  4313  		return nil, BuildErrorResponse(r, err)
  4314  	}
  4315  	defer closeBody(r)
  4316  	return CommandFromJson(r.Body), BuildResponse(r)
  4317  }
  4318  
  4319  // MoveCommand moves a command to a different team.
  4320  func (c *Client4) MoveCommand(teamId string, commandId string) (bool, *Response) {
  4321  	cmr := CommandMoveRequest{TeamId: teamId}
  4322  	r, err := c.DoApiPut(c.GetCommandMoveRoute(commandId), cmr.ToJson())
  4323  	if err != nil {
  4324  		return false, BuildErrorResponse(r, err)
  4325  	}
  4326  	defer closeBody(r)
  4327  	return CheckStatusOK(r), BuildResponse(r)
  4328  }
  4329  
  4330  // DeleteCommand deletes a command based on the provided command id string.
  4331  func (c *Client4) DeleteCommand(commandId string) (bool, *Response) {
  4332  	r, err := c.DoApiDelete(c.GetCommandRoute(commandId))
  4333  	if err != nil {
  4334  		return false, BuildErrorResponse(r, err)
  4335  	}
  4336  	defer closeBody(r)
  4337  	return CheckStatusOK(r), BuildResponse(r)
  4338  }
  4339  
  4340  // ListCommands will retrieve a list of commands available in the team.
  4341  func (c *Client4) ListCommands(teamId string, customOnly bool) ([]*Command, *Response) {
  4342  	query := fmt.Sprintf("?team_id=%v&custom_only=%v", teamId, customOnly)
  4343  	r, err := c.DoApiGet(c.GetCommandsRoute()+query, "")
  4344  	if err != nil {
  4345  		return nil, BuildErrorResponse(r, err)
  4346  	}
  4347  	defer closeBody(r)
  4348  	return CommandListFromJson(r.Body), BuildResponse(r)
  4349  }
  4350  
  4351  // ListCommandAutocompleteSuggestions will retrieve a list of suggestions for a userInput.
  4352  func (c *Client4) ListCommandAutocompleteSuggestions(userInput, teamId string) ([]AutocompleteSuggestion, *Response) {
  4353  	query := fmt.Sprintf("/commands/autocomplete_suggestions?user_input=%v", userInput)
  4354  	r, err := c.DoApiGet(c.GetTeamRoute(teamId)+query, "")
  4355  	if err != nil {
  4356  		return nil, BuildErrorResponse(r, err)
  4357  	}
  4358  	defer closeBody(r)
  4359  	return AutocompleteSuggestionsFromJSON(r.Body), BuildResponse(r)
  4360  }
  4361  
  4362  // GetCommandById will retrieve a command by id.
  4363  func (c *Client4) GetCommandById(cmdId string) (*Command, *Response) {
  4364  	url := fmt.Sprintf("%s/%s", c.GetCommandsRoute(), cmdId)
  4365  	r, err := c.DoApiGet(url, "")
  4366  	if err != nil {
  4367  		return nil, BuildErrorResponse(r, err)
  4368  	}
  4369  	defer closeBody(r)
  4370  	return CommandFromJson(r.Body), BuildResponse(r)
  4371  }
  4372  
  4373  // ExecuteCommand executes a given slash command.
  4374  func (c *Client4) ExecuteCommand(channelId, command string) (*CommandResponse, *Response) {
  4375  	commandArgs := &CommandArgs{
  4376  		ChannelId: channelId,
  4377  		Command:   command,
  4378  	}
  4379  	r, err := c.DoApiPost(c.GetCommandsRoute()+"/execute", commandArgs.ToJson())
  4380  	if err != nil {
  4381  		return nil, BuildErrorResponse(r, err)
  4382  	}
  4383  	defer closeBody(r)
  4384  
  4385  	response, _ := CommandResponseFromJson(r.Body)
  4386  	return response, BuildResponse(r)
  4387  }
  4388  
  4389  // ExecuteCommandWithTeam executes a given slash command against the specified team.
  4390  // Use this when executing slash commands in a DM/GM, since the team id cannot be inferred in that case.
  4391  func (c *Client4) ExecuteCommandWithTeam(channelId, teamId, command string) (*CommandResponse, *Response) {
  4392  	commandArgs := &CommandArgs{
  4393  		ChannelId: channelId,
  4394  		TeamId:    teamId,
  4395  		Command:   command,
  4396  	}
  4397  	r, err := c.DoApiPost(c.GetCommandsRoute()+"/execute", commandArgs.ToJson())
  4398  	if err != nil {
  4399  		return nil, BuildErrorResponse(r, err)
  4400  	}
  4401  	defer closeBody(r)
  4402  
  4403  	response, _ := CommandResponseFromJson(r.Body)
  4404  	return response, BuildResponse(r)
  4405  }
  4406  
  4407  // ListAutocompleteCommands will retrieve a list of commands available in the team.
  4408  func (c *Client4) ListAutocompleteCommands(teamId string) ([]*Command, *Response) {
  4409  	r, err := c.DoApiGet(c.GetTeamAutoCompleteCommandsRoute(teamId), "")
  4410  	if err != nil {
  4411  		return nil, BuildErrorResponse(r, err)
  4412  	}
  4413  	defer closeBody(r)
  4414  	return CommandListFromJson(r.Body), BuildResponse(r)
  4415  }
  4416  
  4417  // RegenCommandToken will create a new token if the user have the right permissions.
  4418  func (c *Client4) RegenCommandToken(commandId string) (string, *Response) {
  4419  	r, err := c.DoApiPut(c.GetCommandRoute(commandId)+"/regen_token", "")
  4420  	if err != nil {
  4421  		return "", BuildErrorResponse(r, err)
  4422  	}
  4423  	defer closeBody(r)
  4424  	return MapFromJson(r.Body)["token"], BuildResponse(r)
  4425  }
  4426  
  4427  // Status Section
  4428  
  4429  // GetUserStatus returns a user based on the provided user id string.
  4430  func (c *Client4) GetUserStatus(userId, etag string) (*Status, *Response) {
  4431  	r, err := c.DoApiGet(c.GetUserStatusRoute(userId), etag)
  4432  	if err != nil {
  4433  		return nil, BuildErrorResponse(r, err)
  4434  	}
  4435  	defer closeBody(r)
  4436  	return StatusFromJson(r.Body), BuildResponse(r)
  4437  }
  4438  
  4439  // GetUsersStatusesByIds returns a list of users status based on the provided user ids.
  4440  func (c *Client4) GetUsersStatusesByIds(userIds []string) ([]*Status, *Response) {
  4441  	r, err := c.DoApiPost(c.GetUserStatusesRoute()+"/ids", ArrayToJson(userIds))
  4442  	if err != nil {
  4443  		return nil, BuildErrorResponse(r, err)
  4444  	}
  4445  	defer closeBody(r)
  4446  	return StatusListFromJson(r.Body), BuildResponse(r)
  4447  }
  4448  
  4449  // UpdateUserStatus sets a user's status based on the provided user id string.
  4450  func (c *Client4) UpdateUserStatus(userId string, userStatus *Status) (*Status, *Response) {
  4451  	r, err := c.DoApiPut(c.GetUserStatusRoute(userId), userStatus.ToJson())
  4452  	if err != nil {
  4453  		return nil, BuildErrorResponse(r, err)
  4454  	}
  4455  	defer closeBody(r)
  4456  	return StatusFromJson(r.Body), BuildResponse(r)
  4457  }
  4458  
  4459  // Emoji Section
  4460  
  4461  // CreateEmoji will save an emoji to the server if the current user has permission
  4462  // to do so. If successful, the provided emoji will be returned with its Id field
  4463  // filled in. Otherwise, an error will be returned.
  4464  func (c *Client4) CreateEmoji(emoji *Emoji, image []byte, filename string) (*Emoji, *Response) {
  4465  	body := &bytes.Buffer{}
  4466  	writer := multipart.NewWriter(body)
  4467  
  4468  	part, err := writer.CreateFormFile("image", filename)
  4469  	if err != nil {
  4470  		return nil, &Response{StatusCode: http.StatusForbidden, Error: NewAppError("CreateEmoji", "model.client.create_emoji.image.app_error", nil, err.Error(), 0)}
  4471  	}
  4472  
  4473  	if _, err := io.Copy(part, bytes.NewBuffer(image)); err != nil {
  4474  		return nil, &Response{StatusCode: http.StatusForbidden, Error: NewAppError("CreateEmoji", "model.client.create_emoji.image.app_error", nil, err.Error(), 0)}
  4475  	}
  4476  
  4477  	if err := writer.WriteField("emoji", emoji.ToJson()); err != nil {
  4478  		return nil, &Response{StatusCode: http.StatusForbidden, Error: NewAppError("CreateEmoji", "model.client.create_emoji.emoji.app_error", nil, err.Error(), 0)}
  4479  	}
  4480  
  4481  	if err := writer.Close(); err != nil {
  4482  		return nil, &Response{StatusCode: http.StatusForbidden, Error: NewAppError("CreateEmoji", "model.client.create_emoji.writer.app_error", nil, err.Error(), 0)}
  4483  	}
  4484  
  4485  	return c.DoEmojiUploadFile(c.GetEmojisRoute(), body.Bytes(), writer.FormDataContentType())
  4486  }
  4487  
  4488  // GetEmojiList returns a page of custom emoji on the system.
  4489  func (c *Client4) GetEmojiList(page, perPage int) ([]*Emoji, *Response) {
  4490  	query := fmt.Sprintf("?page=%v&per_page=%v", page, perPage)
  4491  	r, err := c.DoApiGet(c.GetEmojisRoute()+query, "")
  4492  	if err != nil {
  4493  		return nil, BuildErrorResponse(r, err)
  4494  	}
  4495  	defer closeBody(r)
  4496  	return EmojiListFromJson(r.Body), BuildResponse(r)
  4497  }
  4498  
  4499  // GetSortedEmojiList returns a page of custom emoji on the system sorted based on the sort
  4500  // parameter, blank for no sorting and "name" to sort by emoji names.
  4501  func (c *Client4) GetSortedEmojiList(page, perPage int, sort string) ([]*Emoji, *Response) {
  4502  	query := fmt.Sprintf("?page=%v&per_page=%v&sort=%v", page, perPage, sort)
  4503  	r, err := c.DoApiGet(c.GetEmojisRoute()+query, "")
  4504  	if err != nil {
  4505  		return nil, BuildErrorResponse(r, err)
  4506  	}
  4507  	defer closeBody(r)
  4508  	return EmojiListFromJson(r.Body), BuildResponse(r)
  4509  }
  4510  
  4511  // DeleteEmoji delete an custom emoji on the provided emoji id string.
  4512  func (c *Client4) DeleteEmoji(emojiId string) (bool, *Response) {
  4513  	r, err := c.DoApiDelete(c.GetEmojiRoute(emojiId))
  4514  	if err != nil {
  4515  		return false, BuildErrorResponse(r, err)
  4516  	}
  4517  	defer closeBody(r)
  4518  	return CheckStatusOK(r), BuildResponse(r)
  4519  }
  4520  
  4521  // GetEmoji returns a custom emoji based on the emojiId string.
  4522  func (c *Client4) GetEmoji(emojiId string) (*Emoji, *Response) {
  4523  	r, err := c.DoApiGet(c.GetEmojiRoute(emojiId), "")
  4524  	if err != nil {
  4525  		return nil, BuildErrorResponse(r, err)
  4526  	}
  4527  	defer closeBody(r)
  4528  	return EmojiFromJson(r.Body), BuildResponse(r)
  4529  }
  4530  
  4531  // GetEmojiByName returns a custom emoji based on the name string.
  4532  func (c *Client4) GetEmojiByName(name string) (*Emoji, *Response) {
  4533  	r, err := c.DoApiGet(c.GetEmojiByNameRoute(name), "")
  4534  	if err != nil {
  4535  		return nil, BuildErrorResponse(r, err)
  4536  	}
  4537  	defer closeBody(r)
  4538  	return EmojiFromJson(r.Body), BuildResponse(r)
  4539  }
  4540  
  4541  // GetEmojiImage returns the emoji image.
  4542  func (c *Client4) GetEmojiImage(emojiId string) ([]byte, *Response) {
  4543  	r, apErr := c.DoApiGet(c.GetEmojiRoute(emojiId)+"/image", "")
  4544  	if apErr != nil {
  4545  		return nil, BuildErrorResponse(r, apErr)
  4546  	}
  4547  	defer closeBody(r)
  4548  
  4549  	data, err := ioutil.ReadAll(r.Body)
  4550  	if err != nil {
  4551  		return nil, BuildErrorResponse(r, NewAppError("GetEmojiImage", "model.client.read_file.app_error", nil, err.Error(), r.StatusCode))
  4552  	}
  4553  
  4554  	return data, BuildResponse(r)
  4555  }
  4556  
  4557  // SearchEmoji returns a list of emoji matching some search criteria.
  4558  func (c *Client4) SearchEmoji(search *EmojiSearch) ([]*Emoji, *Response) {
  4559  	r, err := c.DoApiPost(c.GetEmojisRoute()+"/search", search.ToJson())
  4560  	if err != nil {
  4561  		return nil, BuildErrorResponse(r, err)
  4562  	}
  4563  	defer closeBody(r)
  4564  	return EmojiListFromJson(r.Body), BuildResponse(r)
  4565  }
  4566  
  4567  // AutocompleteEmoji returns a list of emoji starting with or matching name.
  4568  func (c *Client4) AutocompleteEmoji(name string, etag string) ([]*Emoji, *Response) {
  4569  	query := fmt.Sprintf("?name=%v", name)
  4570  	r, err := c.DoApiGet(c.GetEmojisRoute()+"/autocomplete"+query, "")
  4571  	if err != nil {
  4572  		return nil, BuildErrorResponse(r, err)
  4573  	}
  4574  	defer closeBody(r)
  4575  	return EmojiListFromJson(r.Body), BuildResponse(r)
  4576  }
  4577  
  4578  // Reaction Section
  4579  
  4580  // SaveReaction saves an emoji reaction for a post. Returns the saved reaction if successful, otherwise an error will be returned.
  4581  func (c *Client4) SaveReaction(reaction *Reaction) (*Reaction, *Response) {
  4582  	r, err := c.DoApiPost(c.GetReactionsRoute(), reaction.ToJson())
  4583  	if err != nil {
  4584  		return nil, BuildErrorResponse(r, err)
  4585  	}
  4586  	defer closeBody(r)
  4587  	return ReactionFromJson(r.Body), BuildResponse(r)
  4588  }
  4589  
  4590  // GetReactions returns a list of reactions to a post.
  4591  func (c *Client4) GetReactions(postId string) ([]*Reaction, *Response) {
  4592  	r, err := c.DoApiGet(c.GetPostRoute(postId)+"/reactions", "")
  4593  	if err != nil {
  4594  		return nil, BuildErrorResponse(r, err)
  4595  	}
  4596  	defer closeBody(r)
  4597  	return ReactionsFromJson(r.Body), BuildResponse(r)
  4598  }
  4599  
  4600  // DeleteReaction deletes reaction of a user in a post.
  4601  func (c *Client4) DeleteReaction(reaction *Reaction) (bool, *Response) {
  4602  	r, err := c.DoApiDelete(c.GetUserRoute(reaction.UserId) + c.GetPostRoute(reaction.PostId) + fmt.Sprintf("/reactions/%v", reaction.EmojiName))
  4603  	if err != nil {
  4604  		return false, BuildErrorResponse(r, err)
  4605  	}
  4606  	defer closeBody(r)
  4607  	return CheckStatusOK(r), BuildResponse(r)
  4608  }
  4609  
  4610  // FetchBulkReactions returns a map of postIds and corresponding reactions
  4611  func (c *Client4) GetBulkReactions(postIds []string) (map[string][]*Reaction, *Response) {
  4612  	r, err := c.DoApiPost(c.GetPostsRoute()+"/ids/reactions", ArrayToJson(postIds))
  4613  	if err != nil {
  4614  		return nil, BuildErrorResponse(r, err)
  4615  	}
  4616  	defer closeBody(r)
  4617  	return MapPostIdToReactionsFromJson(r.Body), BuildResponse(r)
  4618  }
  4619  
  4620  // Timezone Section
  4621  
  4622  // GetSupportedTimezone returns a page of supported timezones on the system.
  4623  func (c *Client4) GetSupportedTimezone() ([]string, *Response) {
  4624  	r, err := c.DoApiGet(c.GetTimezonesRoute(), "")
  4625  	if err != nil {
  4626  		return nil, BuildErrorResponse(r, err)
  4627  	}
  4628  	defer closeBody(r)
  4629  	var timezones []string
  4630  	json.NewDecoder(r.Body).Decode(&timezones)
  4631  	return timezones, BuildResponse(r)
  4632  }
  4633  
  4634  // Open Graph Metadata Section
  4635  
  4636  // OpenGraph return the open graph metadata for a particular url if the site have the metadata.
  4637  func (c *Client4) OpenGraph(url string) (map[string]string, *Response) {
  4638  	requestBody := make(map[string]string)
  4639  	requestBody["url"] = url
  4640  
  4641  	r, err := c.DoApiPost(c.GetOpenGraphRoute(), MapToJson(requestBody))
  4642  	if err != nil {
  4643  		return nil, BuildErrorResponse(r, err)
  4644  	}
  4645  	defer closeBody(r)
  4646  	return MapFromJson(r.Body), BuildResponse(r)
  4647  }
  4648  
  4649  // Jobs Section
  4650  
  4651  // GetJob gets a single job.
  4652  func (c *Client4) GetJob(id string) (*Job, *Response) {
  4653  	r, err := c.DoApiGet(c.GetJobsRoute()+fmt.Sprintf("/%v", id), "")
  4654  	if err != nil {
  4655  		return nil, BuildErrorResponse(r, err)
  4656  	}
  4657  	defer closeBody(r)
  4658  	return JobFromJson(r.Body), BuildResponse(r)
  4659  }
  4660  
  4661  // GetJobs gets all jobs, sorted with the job that was created most recently first.
  4662  func (c *Client4) GetJobs(page int, perPage int) ([]*Job, *Response) {
  4663  	r, err := c.DoApiGet(c.GetJobsRoute()+fmt.Sprintf("?page=%v&per_page=%v", page, perPage), "")
  4664  	if err != nil {
  4665  		return nil, BuildErrorResponse(r, err)
  4666  	}
  4667  	defer closeBody(r)
  4668  	return JobsFromJson(r.Body), BuildResponse(r)
  4669  }
  4670  
  4671  // GetJobsByType gets all jobs of a given type, sorted with the job that was created most recently first.
  4672  func (c *Client4) GetJobsByType(jobType string, page int, perPage int) ([]*Job, *Response) {
  4673  	r, err := c.DoApiGet(c.GetJobsRoute()+fmt.Sprintf("/type/%v?page=%v&per_page=%v", jobType, page, perPage), "")
  4674  	if err != nil {
  4675  		return nil, BuildErrorResponse(r, err)
  4676  	}
  4677  	defer closeBody(r)
  4678  	return JobsFromJson(r.Body), BuildResponse(r)
  4679  }
  4680  
  4681  // CreateJob creates a job based on the provided job struct.
  4682  func (c *Client4) CreateJob(job *Job) (*Job, *Response) {
  4683  	r, err := c.DoApiPost(c.GetJobsRoute(), job.ToJson())
  4684  	if err != nil {
  4685  		return nil, BuildErrorResponse(r, err)
  4686  	}
  4687  	defer closeBody(r)
  4688  	return JobFromJson(r.Body), BuildResponse(r)
  4689  }
  4690  
  4691  // CancelJob requests the cancellation of the job with the provided Id.
  4692  func (c *Client4) CancelJob(jobId string) (bool, *Response) {
  4693  	r, err := c.DoApiPost(c.GetJobsRoute()+fmt.Sprintf("/%v/cancel", jobId), "")
  4694  	if err != nil {
  4695  		return false, BuildErrorResponse(r, err)
  4696  	}
  4697  	defer closeBody(r)
  4698  	return CheckStatusOK(r), BuildResponse(r)
  4699  }
  4700  
  4701  // DownloadJob downloads the results of the job
  4702  func (c *Client4) DownloadJob(jobId string) ([]byte, *Response) {
  4703  	r, appErr := c.DoApiGet(c.GetJobsRoute()+fmt.Sprintf("/%v/download", jobId), "")
  4704  	if appErr != nil {
  4705  		return nil, BuildErrorResponse(r, appErr)
  4706  	}
  4707  	defer closeBody(r)
  4708  
  4709  	data, err := ioutil.ReadAll(r.Body)
  4710  	if err != nil {
  4711  		return nil, BuildErrorResponse(r, NewAppError("GetFile", "model.client.read_job_result_file.app_error", nil, err.Error(), r.StatusCode))
  4712  	}
  4713  	return data, BuildResponse(r)
  4714  }
  4715  
  4716  // Roles Section
  4717  
  4718  // GetRole gets a single role by ID.
  4719  func (c *Client4) GetRole(id string) (*Role, *Response) {
  4720  	r, err := c.DoApiGet(c.GetRolesRoute()+fmt.Sprintf("/%v", id), "")
  4721  	if err != nil {
  4722  		return nil, BuildErrorResponse(r, err)
  4723  	}
  4724  	defer closeBody(r)
  4725  	return RoleFromJson(r.Body), BuildResponse(r)
  4726  }
  4727  
  4728  // GetRoleByName gets a single role by Name.
  4729  func (c *Client4) GetRoleByName(name string) (*Role, *Response) {
  4730  	r, err := c.DoApiGet(c.GetRolesRoute()+fmt.Sprintf("/name/%v", name), "")
  4731  	if err != nil {
  4732  		return nil, BuildErrorResponse(r, err)
  4733  	}
  4734  	defer closeBody(r)
  4735  	return RoleFromJson(r.Body), BuildResponse(r)
  4736  }
  4737  
  4738  // GetRolesByNames returns a list of roles based on the provided role names.
  4739  func (c *Client4) GetRolesByNames(roleNames []string) ([]*Role, *Response) {
  4740  	r, err := c.DoApiPost(c.GetRolesRoute()+"/names", ArrayToJson(roleNames))
  4741  	if err != nil {
  4742  		return nil, BuildErrorResponse(r, err)
  4743  	}
  4744  	defer closeBody(r)
  4745  	return RoleListFromJson(r.Body), BuildResponse(r)
  4746  }
  4747  
  4748  // PatchRole partially updates a role in the system. Any missing fields are not updated.
  4749  func (c *Client4) PatchRole(roleId string, patch *RolePatch) (*Role, *Response) {
  4750  	r, err := c.DoApiPut(c.GetRolesRoute()+fmt.Sprintf("/%v/patch", roleId), patch.ToJson())
  4751  	if err != nil {
  4752  		return nil, BuildErrorResponse(r, err)
  4753  	}
  4754  	defer closeBody(r)
  4755  	return RoleFromJson(r.Body), BuildResponse(r)
  4756  }
  4757  
  4758  // Schemes Section
  4759  
  4760  // CreateScheme creates a new Scheme.
  4761  func (c *Client4) CreateScheme(scheme *Scheme) (*Scheme, *Response) {
  4762  	r, err := c.DoApiPost(c.GetSchemesRoute(), scheme.ToJson())
  4763  	if err != nil {
  4764  		return nil, BuildErrorResponse(r, err)
  4765  	}
  4766  	defer closeBody(r)
  4767  	return SchemeFromJson(r.Body), BuildResponse(r)
  4768  }
  4769  
  4770  // GetScheme gets a single scheme by ID.
  4771  func (c *Client4) GetScheme(id string) (*Scheme, *Response) {
  4772  	r, err := c.DoApiGet(c.GetSchemeRoute(id), "")
  4773  	if err != nil {
  4774  		return nil, BuildErrorResponse(r, err)
  4775  	}
  4776  	defer closeBody(r)
  4777  	return SchemeFromJson(r.Body), BuildResponse(r)
  4778  }
  4779  
  4780  // GetSchemes gets all schemes, sorted with the most recently created first, optionally filtered by scope.
  4781  func (c *Client4) GetSchemes(scope string, page int, perPage int) ([]*Scheme, *Response) {
  4782  	r, err := c.DoApiGet(c.GetSchemesRoute()+fmt.Sprintf("?scope=%v&page=%v&per_page=%v", scope, page, perPage), "")
  4783  	if err != nil {
  4784  		return nil, BuildErrorResponse(r, err)
  4785  	}
  4786  	defer closeBody(r)
  4787  	return SchemesFromJson(r.Body), BuildResponse(r)
  4788  }
  4789  
  4790  // DeleteScheme deletes a single scheme by ID.
  4791  func (c *Client4) DeleteScheme(id string) (bool, *Response) {
  4792  	r, err := c.DoApiDelete(c.GetSchemeRoute(id))
  4793  	if err != nil {
  4794  		return false, BuildErrorResponse(r, err)
  4795  	}
  4796  	defer closeBody(r)
  4797  	return CheckStatusOK(r), BuildResponse(r)
  4798  }
  4799  
  4800  // PatchScheme partially updates a scheme in the system. Any missing fields are not updated.
  4801  func (c *Client4) PatchScheme(id string, patch *SchemePatch) (*Scheme, *Response) {
  4802  	r, err := c.DoApiPut(c.GetSchemeRoute(id)+"/patch", patch.ToJson())
  4803  	if err != nil {
  4804  		return nil, BuildErrorResponse(r, err)
  4805  	}
  4806  	defer closeBody(r)
  4807  	return SchemeFromJson(r.Body), BuildResponse(r)
  4808  }
  4809  
  4810  // GetTeamsForScheme gets the teams using this scheme, sorted alphabetically by display name.
  4811  func (c *Client4) GetTeamsForScheme(schemeId string, page int, perPage int) ([]*Team, *Response) {
  4812  	r, err := c.DoApiGet(c.GetSchemeRoute(schemeId)+fmt.Sprintf("/teams?page=%v&per_page=%v", page, perPage), "")
  4813  	if err != nil {
  4814  		return nil, BuildErrorResponse(r, err)
  4815  	}
  4816  	defer closeBody(r)
  4817  	return TeamListFromJson(r.Body), BuildResponse(r)
  4818  }
  4819  
  4820  // GetChannelsForScheme gets the channels using this scheme, sorted alphabetically by display name.
  4821  func (c *Client4) GetChannelsForScheme(schemeId string, page int, perPage int) (ChannelList, *Response) {
  4822  	r, err := c.DoApiGet(c.GetSchemeRoute(schemeId)+fmt.Sprintf("/channels?page=%v&per_page=%v", page, perPage), "")
  4823  	if err != nil {
  4824  		return nil, BuildErrorResponse(r, err)
  4825  	}
  4826  	defer closeBody(r)
  4827  	return *ChannelListFromJson(r.Body), BuildResponse(r)
  4828  }
  4829  
  4830  // Plugin Section
  4831  
  4832  // UploadPlugin takes an io.Reader stream pointing to the contents of a .tar.gz plugin.
  4833  // WARNING: PLUGINS ARE STILL EXPERIMENTAL. THIS FUNCTION IS SUBJECT TO CHANGE.
  4834  func (c *Client4) UploadPlugin(file io.Reader) (*Manifest, *Response) {
  4835  	return c.uploadPlugin(file, false)
  4836  }
  4837  
  4838  func (c *Client4) UploadPluginForced(file io.Reader) (*Manifest, *Response) {
  4839  	return c.uploadPlugin(file, true)
  4840  }
  4841  
  4842  func (c *Client4) uploadPlugin(file io.Reader, force bool) (*Manifest, *Response) {
  4843  	body := new(bytes.Buffer)
  4844  	writer := multipart.NewWriter(body)
  4845  
  4846  	if force {
  4847  		err := writer.WriteField("force", c.boolString(true))
  4848  		if err != nil {
  4849  			return nil, &Response{Error: NewAppError("UploadPlugin", "model.client.writer.app_error", nil, err.Error(), 0)}
  4850  		}
  4851  	}
  4852  
  4853  	part, err := writer.CreateFormFile("plugin", "plugin.tar.gz")
  4854  	if err != nil {
  4855  		return nil, &Response{Error: NewAppError("UploadPlugin", "model.client.writer.app_error", nil, err.Error(), 0)}
  4856  	}
  4857  
  4858  	if _, err = io.Copy(part, file); err != nil {
  4859  		return nil, &Response{Error: NewAppError("UploadPlugin", "model.client.writer.app_error", nil, err.Error(), 0)}
  4860  	}
  4861  
  4862  	if err = writer.Close(); err != nil {
  4863  		return nil, &Response{Error: NewAppError("UploadPlugin", "model.client.writer.app_error", nil, err.Error(), 0)}
  4864  	}
  4865  
  4866  	rq, err := http.NewRequest("POST", c.ApiUrl+c.GetPluginsRoute(), body)
  4867  	if err != nil {
  4868  		return nil, &Response{Error: NewAppError("UploadPlugin", "model.client.connecting.app_error", nil, err.Error(), http.StatusBadRequest)}
  4869  	}
  4870  	rq.Header.Set("Content-Type", writer.FormDataContentType())
  4871  
  4872  	if len(c.AuthToken) > 0 {
  4873  		rq.Header.Set(HEADER_AUTH, c.AuthType+" "+c.AuthToken)
  4874  	}
  4875  
  4876  	rp, err := c.HttpClient.Do(rq)
  4877  	if err != nil || rp == nil {
  4878  		return nil, BuildErrorResponse(rp, NewAppError("UploadPlugin", "model.client.connecting.app_error", nil, err.Error(), 0))
  4879  	}
  4880  	defer closeBody(rp)
  4881  
  4882  	if rp.StatusCode >= 300 {
  4883  		return nil, BuildErrorResponse(rp, AppErrorFromJson(rp.Body))
  4884  	}
  4885  
  4886  	return ManifestFromJson(rp.Body), BuildResponse(rp)
  4887  }
  4888  
  4889  func (c *Client4) InstallPluginFromUrl(downloadUrl string, force bool) (*Manifest, *Response) {
  4890  	forceStr := c.boolString(force)
  4891  
  4892  	url := fmt.Sprintf("%s?plugin_download_url=%s&force=%s", c.GetPluginsRoute()+"/install_from_url", url.QueryEscape(downloadUrl), forceStr)
  4893  	r, err := c.DoApiPost(url, "")
  4894  	if err != nil {
  4895  		return nil, BuildErrorResponse(r, err)
  4896  	}
  4897  	defer closeBody(r)
  4898  	return ManifestFromJson(r.Body), BuildResponse(r)
  4899  }
  4900  
  4901  // InstallMarketplacePlugin will install marketplace plugin.
  4902  // WARNING: PLUGINS ARE STILL EXPERIMENTAL. THIS FUNCTION IS SUBJECT TO CHANGE.
  4903  func (c *Client4) InstallMarketplacePlugin(request *InstallMarketplacePluginRequest) (*Manifest, *Response) {
  4904  	json, err := request.ToJson()
  4905  	if err != nil {
  4906  		return nil, &Response{Error: NewAppError("InstallMarketplacePlugin", "model.client.plugin_request_to_json.app_error", nil, err.Error(), http.StatusBadRequest)}
  4907  	}
  4908  	r, appErr := c.DoApiPost(c.GetPluginsRoute()+"/marketplace", json)
  4909  	if appErr != nil {
  4910  		return nil, BuildErrorResponse(r, appErr)
  4911  	}
  4912  	defer closeBody(r)
  4913  	return ManifestFromJson(r.Body), BuildResponse(r)
  4914  }
  4915  
  4916  // GetPlugins will return a list of plugin manifests for currently active plugins.
  4917  // WARNING: PLUGINS ARE STILL EXPERIMENTAL. THIS FUNCTION IS SUBJECT TO CHANGE.
  4918  func (c *Client4) GetPlugins() (*PluginsResponse, *Response) {
  4919  	r, err := c.DoApiGet(c.GetPluginsRoute(), "")
  4920  	if err != nil {
  4921  		return nil, BuildErrorResponse(r, err)
  4922  	}
  4923  	defer closeBody(r)
  4924  	return PluginsResponseFromJson(r.Body), BuildResponse(r)
  4925  }
  4926  
  4927  // GetPluginStatuses will return the plugins installed on any server in the cluster, for reporting
  4928  // to the administrator via the system console.
  4929  // WARNING: PLUGINS ARE STILL EXPERIMENTAL. THIS FUNCTION IS SUBJECT TO CHANGE.
  4930  func (c *Client4) GetPluginStatuses() (PluginStatuses, *Response) {
  4931  	r, err := c.DoApiGet(c.GetPluginsRoute()+"/statuses", "")
  4932  	if err != nil {
  4933  		return nil, BuildErrorResponse(r, err)
  4934  	}
  4935  	defer closeBody(r)
  4936  	return PluginStatusesFromJson(r.Body), BuildResponse(r)
  4937  }
  4938  
  4939  // RemovePlugin will disable and delete a plugin.
  4940  // WARNING: PLUGINS ARE STILL EXPERIMENTAL. THIS FUNCTION IS SUBJECT TO CHANGE.
  4941  func (c *Client4) RemovePlugin(id string) (bool, *Response) {
  4942  	r, err := c.DoApiDelete(c.GetPluginRoute(id))
  4943  	if err != nil {
  4944  		return false, BuildErrorResponse(r, err)
  4945  	}
  4946  	defer closeBody(r)
  4947  	return CheckStatusOK(r), BuildResponse(r)
  4948  }
  4949  
  4950  // GetWebappPlugins will return a list of plugins that the webapp should download.
  4951  // WARNING: PLUGINS ARE STILL EXPERIMENTAL. THIS FUNCTION IS SUBJECT TO CHANGE.
  4952  func (c *Client4) GetWebappPlugins() ([]*Manifest, *Response) {
  4953  	r, err := c.DoApiGet(c.GetPluginsRoute()+"/webapp", "")
  4954  	if err != nil {
  4955  		return nil, BuildErrorResponse(r, err)
  4956  	}
  4957  	defer closeBody(r)
  4958  	return ManifestListFromJson(r.Body), BuildResponse(r)
  4959  }
  4960  
  4961  // EnablePlugin will enable an plugin installed.
  4962  // WARNING: PLUGINS ARE STILL EXPERIMENTAL. THIS FUNCTION IS SUBJECT TO CHANGE.
  4963  func (c *Client4) EnablePlugin(id string) (bool, *Response) {
  4964  	r, err := c.DoApiPost(c.GetPluginRoute(id)+"/enable", "")
  4965  	if err != nil {
  4966  		return false, BuildErrorResponse(r, err)
  4967  	}
  4968  	defer closeBody(r)
  4969  	return CheckStatusOK(r), BuildResponse(r)
  4970  }
  4971  
  4972  // DisablePlugin will disable an enabled plugin.
  4973  // WARNING: PLUGINS ARE STILL EXPERIMENTAL. THIS FUNCTION IS SUBJECT TO CHANGE.
  4974  func (c *Client4) DisablePlugin(id string) (bool, *Response) {
  4975  	r, err := c.DoApiPost(c.GetPluginRoute(id)+"/disable", "")
  4976  	if err != nil {
  4977  		return false, BuildErrorResponse(r, err)
  4978  	}
  4979  	defer closeBody(r)
  4980  	return CheckStatusOK(r), BuildResponse(r)
  4981  }
  4982  
  4983  // GetMarketplacePlugins will return a list of plugins that an admin can install.
  4984  // WARNING: PLUGINS ARE STILL EXPERIMENTAL. THIS FUNCTION IS SUBJECT TO CHANGE.
  4985  func (c *Client4) GetMarketplacePlugins(filter *MarketplacePluginFilter) ([]*MarketplacePlugin, *Response) {
  4986  	route := c.GetPluginsRoute() + "/marketplace"
  4987  	u, parseErr := url.Parse(route)
  4988  	if parseErr != nil {
  4989  		return nil, &Response{Error: NewAppError("GetMarketplacePlugins", "model.client.parse_plugins.app_error", nil, parseErr.Error(), http.StatusBadRequest)}
  4990  	}
  4991  
  4992  	filter.ApplyToURL(u)
  4993  
  4994  	r, err := c.DoApiGet(u.String(), "")
  4995  	if err != nil {
  4996  		return nil, BuildErrorResponse(r, err)
  4997  	}
  4998  	defer closeBody(r)
  4999  
  5000  	plugins, readerErr := MarketplacePluginsFromReader(r.Body)
  5001  	if readerErr != nil {
  5002  		return nil, BuildErrorResponse(r, NewAppError(route, "model.client.parse_plugins.app_error", nil, err.Error(), http.StatusBadRequest))
  5003  	}
  5004  
  5005  	return plugins, BuildResponse(r)
  5006  }
  5007  
  5008  // UpdateChannelScheme will update a channel's scheme.
  5009  func (c *Client4) UpdateChannelScheme(channelId, schemeId string) (bool, *Response) {
  5010  	sip := &SchemeIDPatch{SchemeID: &schemeId}
  5011  	r, err := c.DoApiPut(c.GetChannelSchemeRoute(channelId), sip.ToJson())
  5012  	if err != nil {
  5013  		return false, BuildErrorResponse(r, err)
  5014  	}
  5015  	defer closeBody(r)
  5016  	return CheckStatusOK(r), BuildResponse(r)
  5017  }
  5018  
  5019  // UpdateTeamScheme will update a team's scheme.
  5020  func (c *Client4) UpdateTeamScheme(teamId, schemeId string) (bool, *Response) {
  5021  	sip := &SchemeIDPatch{SchemeID: &schemeId}
  5022  	r, err := c.DoApiPut(c.GetTeamSchemeRoute(teamId), sip.ToJson())
  5023  	if err != nil {
  5024  		return false, BuildErrorResponse(r, err)
  5025  	}
  5026  	defer closeBody(r)
  5027  	return CheckStatusOK(r), BuildResponse(r)
  5028  }
  5029  
  5030  // GetRedirectLocation retrieves the value of the 'Location' header of an HTTP response for a given URL.
  5031  func (c *Client4) GetRedirectLocation(urlParam, etag string) (string, *Response) {
  5032  	url := fmt.Sprintf("%s?url=%s", c.GetRedirectLocationRoute(), url.QueryEscape(urlParam))
  5033  	r, err := c.DoApiGet(url, etag)
  5034  	if err != nil {
  5035  		return "", BuildErrorResponse(r, err)
  5036  	}
  5037  	defer closeBody(r)
  5038  	return MapFromJson(r.Body)["location"], BuildResponse(r)
  5039  }
  5040  
  5041  // SetServerBusy will mark the server as busy, which disables non-critical services for `secs` seconds.
  5042  func (c *Client4) SetServerBusy(secs int) (bool, *Response) {
  5043  	url := fmt.Sprintf("%s?seconds=%d", c.GetServerBusyRoute(), secs)
  5044  	r, err := c.DoApiPost(url, "")
  5045  	if err != nil {
  5046  		return false, BuildErrorResponse(r, err)
  5047  	}
  5048  	defer closeBody(r)
  5049  	return CheckStatusOK(r), BuildResponse(r)
  5050  }
  5051  
  5052  // ClearServerBusy will mark the server as not busy.
  5053  func (c *Client4) ClearServerBusy() (bool, *Response) {
  5054  	r, err := c.DoApiDelete(c.GetServerBusyRoute())
  5055  	if err != nil {
  5056  		return false, BuildErrorResponse(r, err)
  5057  	}
  5058  	defer closeBody(r)
  5059  	return CheckStatusOK(r), BuildResponse(r)
  5060  }
  5061  
  5062  // GetServerBusy returns the current ServerBusyState including the time when a server marked busy
  5063  // will automatically have the flag cleared.
  5064  func (c *Client4) GetServerBusy() (*ServerBusyState, *Response) {
  5065  	r, err := c.DoApiGet(c.GetServerBusyRoute(), "")
  5066  	if err != nil {
  5067  		return nil, BuildErrorResponse(r, err)
  5068  	}
  5069  	defer closeBody(r)
  5070  
  5071  	sbs := ServerBusyStateFromJson(r.Body)
  5072  	return sbs, BuildResponse(r)
  5073  }
  5074  
  5075  // GetServerBusyExpires returns the time when a server marked busy
  5076  // will automatically have the flag cleared.
  5077  //
  5078  // Deprecated: Use GetServerBusy instead.
  5079  func (c *Client4) GetServerBusyExpires() (*time.Time, *Response) {
  5080  	r, err := c.DoApiGet(c.GetServerBusyRoute(), "")
  5081  	if err != nil {
  5082  		return nil, BuildErrorResponse(r, err)
  5083  	}
  5084  	defer closeBody(r)
  5085  
  5086  	sbs := ServerBusyStateFromJson(r.Body)
  5087  	expires := time.Unix(sbs.Expires, 0)
  5088  	return &expires, BuildResponse(r)
  5089  }
  5090  
  5091  // RegisterTermsOfServiceAction saves action performed by a user against a specific terms of service.
  5092  func (c *Client4) RegisterTermsOfServiceAction(userId, termsOfServiceId string, accepted bool) (*bool, *Response) {
  5093  	url := c.GetUserTermsOfServiceRoute(userId)
  5094  	data := map[string]interface{}{"termsOfServiceId": termsOfServiceId, "accepted": accepted}
  5095  	r, err := c.DoApiPost(url, StringInterfaceToJson(data))
  5096  	if err != nil {
  5097  		return nil, BuildErrorResponse(r, err)
  5098  	}
  5099  	defer closeBody(r)
  5100  	return NewBool(CheckStatusOK(r)), BuildResponse(r)
  5101  }
  5102  
  5103  // GetTermsOfService fetches the latest terms of service
  5104  func (c *Client4) GetTermsOfService(etag string) (*TermsOfService, *Response) {
  5105  	url := c.GetTermsOfServiceRoute()
  5106  	r, err := c.DoApiGet(url, etag)
  5107  	if err != nil {
  5108  		return nil, BuildErrorResponse(r, err)
  5109  	}
  5110  	defer closeBody(r)
  5111  	return TermsOfServiceFromJson(r.Body), BuildResponse(r)
  5112  }
  5113  
  5114  // GetUserTermsOfService fetches user's latest terms of service action if the latest action was for acceptance.
  5115  func (c *Client4) GetUserTermsOfService(userId, etag string) (*UserTermsOfService, *Response) {
  5116  	url := c.GetUserTermsOfServiceRoute(userId)
  5117  	r, err := c.DoApiGet(url, etag)
  5118  	if err != nil {
  5119  		return nil, BuildErrorResponse(r, err)
  5120  	}
  5121  	defer closeBody(r)
  5122  	return UserTermsOfServiceFromJson(r.Body), BuildResponse(r)
  5123  }
  5124  
  5125  // CreateTermsOfService creates new terms of service.
  5126  func (c *Client4) CreateTermsOfService(text, userId string) (*TermsOfService, *Response) {
  5127  	url := c.GetTermsOfServiceRoute()
  5128  	data := map[string]interface{}{"text": text}
  5129  	r, err := c.DoApiPost(url, StringInterfaceToJson(data))
  5130  	if err != nil {
  5131  		return nil, BuildErrorResponse(r, err)
  5132  	}
  5133  	defer closeBody(r)
  5134  	return TermsOfServiceFromJson(r.Body), BuildResponse(r)
  5135  }
  5136  
  5137  func (c *Client4) GetGroup(groupID, etag string) (*Group, *Response) {
  5138  	r, appErr := c.DoApiGet(c.GetGroupRoute(groupID), etag)
  5139  	if appErr != nil {
  5140  		return nil, BuildErrorResponse(r, appErr)
  5141  	}
  5142  	defer closeBody(r)
  5143  	return GroupFromJson(r.Body), BuildResponse(r)
  5144  }
  5145  
  5146  func (c *Client4) PatchGroup(groupID string, patch *GroupPatch) (*Group, *Response) {
  5147  	payload, _ := json.Marshal(patch)
  5148  	r, appErr := c.DoApiPut(c.GetGroupRoute(groupID)+"/patch", string(payload))
  5149  	if appErr != nil {
  5150  		return nil, BuildErrorResponse(r, appErr)
  5151  	}
  5152  	defer closeBody(r)
  5153  	return GroupFromJson(r.Body), BuildResponse(r)
  5154  }
  5155  
  5156  func (c *Client4) LinkGroupSyncable(groupID, syncableID string, syncableType GroupSyncableType, patch *GroupSyncablePatch) (*GroupSyncable, *Response) {
  5157  	payload, _ := json.Marshal(patch)
  5158  	url := fmt.Sprintf("%s/link", c.GetGroupSyncableRoute(groupID, syncableID, syncableType))
  5159  	r, appErr := c.DoApiPost(url, string(payload))
  5160  	if appErr != nil {
  5161  		return nil, BuildErrorResponse(r, appErr)
  5162  	}
  5163  	defer closeBody(r)
  5164  	return GroupSyncableFromJson(r.Body), BuildResponse(r)
  5165  }
  5166  
  5167  func (c *Client4) UnlinkGroupSyncable(groupID, syncableID string, syncableType GroupSyncableType) *Response {
  5168  	url := fmt.Sprintf("%s/link", c.GetGroupSyncableRoute(groupID, syncableID, syncableType))
  5169  	r, appErr := c.DoApiDelete(url)
  5170  	if appErr != nil {
  5171  		return BuildErrorResponse(r, appErr)
  5172  	}
  5173  	defer closeBody(r)
  5174  	return BuildResponse(r)
  5175  }
  5176  
  5177  func (c *Client4) GetGroupSyncable(groupID, syncableID string, syncableType GroupSyncableType, etag string) (*GroupSyncable, *Response) {
  5178  	r, appErr := c.DoApiGet(c.GetGroupSyncableRoute(groupID, syncableID, syncableType), etag)
  5179  	if appErr != nil {
  5180  		return nil, BuildErrorResponse(r, appErr)
  5181  	}
  5182  	defer closeBody(r)
  5183  	return GroupSyncableFromJson(r.Body), BuildResponse(r)
  5184  }
  5185  
  5186  func (c *Client4) GetGroupSyncables(groupID string, syncableType GroupSyncableType, etag string) ([]*GroupSyncable, *Response) {
  5187  	r, appErr := c.DoApiGet(c.GetGroupSyncablesRoute(groupID, syncableType), etag)
  5188  	if appErr != nil {
  5189  		return nil, BuildErrorResponse(r, appErr)
  5190  	}
  5191  	defer closeBody(r)
  5192  	return GroupSyncablesFromJson(r.Body), BuildResponse(r)
  5193  }
  5194  
  5195  func (c *Client4) PatchGroupSyncable(groupID, syncableID string, syncableType GroupSyncableType, patch *GroupSyncablePatch) (*GroupSyncable, *Response) {
  5196  	payload, _ := json.Marshal(patch)
  5197  	r, appErr := c.DoApiPut(c.GetGroupSyncableRoute(groupID, syncableID, syncableType)+"/patch", string(payload))
  5198  	if appErr != nil {
  5199  		return nil, BuildErrorResponse(r, appErr)
  5200  	}
  5201  	defer closeBody(r)
  5202  	return GroupSyncableFromJson(r.Body), BuildResponse(r)
  5203  }
  5204  
  5205  func (c *Client4) TeamMembersMinusGroupMembers(teamID string, groupIDs []string, page, perPage int, etag string) ([]*UserWithGroups, int64, *Response) {
  5206  	groupIDStr := strings.Join(groupIDs, ",")
  5207  	query := fmt.Sprintf("?group_ids=%s&page=%d&per_page=%d", groupIDStr, page, perPage)
  5208  	r, err := c.DoApiGet(c.GetTeamRoute(teamID)+"/members_minus_group_members"+query, etag)
  5209  	if err != nil {
  5210  		return nil, 0, BuildErrorResponse(r, err)
  5211  	}
  5212  	defer closeBody(r)
  5213  	ugc := UsersWithGroupsAndCountFromJson(r.Body)
  5214  	return ugc.Users, ugc.Count, BuildResponse(r)
  5215  }
  5216  
  5217  func (c *Client4) ChannelMembersMinusGroupMembers(channelID string, groupIDs []string, page, perPage int, etag string) ([]*UserWithGroups, int64, *Response) {
  5218  	groupIDStr := strings.Join(groupIDs, ",")
  5219  	query := fmt.Sprintf("?group_ids=%s&page=%d&per_page=%d", groupIDStr, page, perPage)
  5220  	r, err := c.DoApiGet(c.GetChannelRoute(channelID)+"/members_minus_group_members"+query, etag)
  5221  	if err != nil {
  5222  		return nil, 0, BuildErrorResponse(r, err)
  5223  	}
  5224  	defer closeBody(r)
  5225  	ugc := UsersWithGroupsAndCountFromJson(r.Body)
  5226  	return ugc.Users, ugc.Count, BuildResponse(r)
  5227  }
  5228  
  5229  func (c *Client4) PatchConfig(config *Config) (*Config, *Response) {
  5230  	r, err := c.DoApiPut(c.GetConfigRoute()+"/patch", config.ToJson())
  5231  	if err != nil {
  5232  		return nil, BuildErrorResponse(r, err)
  5233  	}
  5234  	defer closeBody(r)
  5235  	return ConfigFromJson(r.Body), BuildResponse(r)
  5236  }
  5237  
  5238  func (c *Client4) GetChannelModerations(channelID string, etag string) ([]*ChannelModeration, *Response) {
  5239  	r, err := c.DoApiGet(c.GetChannelRoute(channelID)+"/moderations", etag)
  5240  	if err != nil {
  5241  		return nil, BuildErrorResponse(r, err)
  5242  	}
  5243  	defer closeBody(r)
  5244  	return ChannelModerationsFromJson(r.Body), BuildResponse(r)
  5245  }
  5246  
  5247  func (c *Client4) PatchChannelModerations(channelID string, patch []*ChannelModerationPatch) ([]*ChannelModeration, *Response) {
  5248  	payload, _ := json.Marshal(patch)
  5249  	r, err := c.DoApiPut(c.GetChannelRoute(channelID)+"/moderations/patch", string(payload))
  5250  	if err != nil {
  5251  		return nil, BuildErrorResponse(r, err)
  5252  	}
  5253  	defer closeBody(r)
  5254  	return ChannelModerationsFromJson(r.Body), BuildResponse(r)
  5255  }
  5256  
  5257  func (c *Client4) GetKnownUsers() ([]string, *Response) {
  5258  	r, err := c.DoApiGet(c.GetUsersRoute()+"/known", "")
  5259  	if err != nil {
  5260  		return nil, BuildErrorResponse(r, err)
  5261  	}
  5262  	defer closeBody(r)
  5263  	var userIds []string
  5264  	json.NewDecoder(r.Body).Decode(&userIds)
  5265  	return userIds, BuildResponse(r)
  5266  }
  5267  
  5268  // PublishUserTyping publishes a user is typing websocket event based on the provided TypingRequest.
  5269  func (c *Client4) PublishUserTyping(userID string, typingRequest TypingRequest) (bool, *Response) {
  5270  	r, err := c.DoApiPost(c.GetPublishUserTypingRoute(userID), typingRequest.ToJson())
  5271  	if err != nil {
  5272  		return false, BuildErrorResponse(r, err)
  5273  	}
  5274  	defer closeBody(r)
  5275  	return CheckStatusOK(r), BuildResponse(r)
  5276  }
  5277  
  5278  func (c *Client4) GetChannelMemberCountsByGroup(channelID string, includeTimezones bool, etag string) ([]*ChannelMemberCountByGroup, *Response) {
  5279  	r, err := c.DoApiGet(c.GetChannelRoute(channelID)+"/member_counts_by_group?include_timezones="+strconv.FormatBool(includeTimezones), etag)
  5280  	if err != nil {
  5281  		return nil, BuildErrorResponse(r, err)
  5282  	}
  5283  	defer closeBody(r)
  5284  	return ChannelMemberCountsByGroupFromJson(r.Body), BuildResponse(r)
  5285  }
  5286  
  5287  // RequestTrialLicense will request a trial license and install it in the server
  5288  func (c *Client4) RequestTrialLicense(users int) (bool, *Response) {
  5289  	b, _ := json.Marshal(map[string]int{"users": users})
  5290  	r, err := c.DoApiPost("/trial-license", string(b))
  5291  	if err != nil {
  5292  		return false, BuildErrorResponse(r, err)
  5293  	}
  5294  	defer closeBody(r)
  5295  	return CheckStatusOK(r), BuildResponse(r)
  5296  }
  5297  
  5298  // GetGroupStats retrieves stats for a Mattermost Group
  5299  func (c *Client4) GetGroupStats(groupID string) (*GroupStats, *Response) {
  5300  	r, appErr := c.DoApiGet(c.GetGroupRoute(groupID)+"/stats", "")
  5301  	if appErr != nil {
  5302  		return nil, BuildErrorResponse(r, appErr)
  5303  	}
  5304  	defer closeBody(r)
  5305  	return GroupStatsFromJson(r.Body), BuildResponse(r)
  5306  }
  5307  
  5308  func (c *Client4) GetSidebarCategoriesForTeamForUser(userID, teamID, etag string) (*OrderedSidebarCategories, *Response) {
  5309  	route := c.GetUserCategoryRoute(userID, teamID)
  5310  	r, appErr := c.DoApiGet(route, etag)
  5311  	if appErr != nil {
  5312  		return nil, BuildErrorResponse(r, appErr)
  5313  	}
  5314  	cat, err := OrderedSidebarCategoriesFromJson(r.Body)
  5315  	if err != nil {
  5316  		return nil, BuildErrorResponse(r, NewAppError("Client4.GetSidebarCategoriesForTeamForUser", "model.utils.decode_json.app_error", nil, err.Error(), r.StatusCode))
  5317  	}
  5318  	return cat, BuildResponse(r)
  5319  }
  5320  
  5321  func (c *Client4) CreateSidebarCategoryForTeamForUser(userID, teamID string, category *SidebarCategoryWithChannels) (*SidebarCategoryWithChannels, *Response) {
  5322  	payload, _ := json.Marshal(category)
  5323  	route := c.GetUserCategoryRoute(userID, teamID)
  5324  	r, appErr := c.doApiPostBytes(route, payload)
  5325  	if appErr != nil {
  5326  		return nil, BuildErrorResponse(r, appErr)
  5327  	}
  5328  	defer closeBody(r)
  5329  	cat, err := SidebarCategoryFromJson(r.Body)
  5330  	if err != nil {
  5331  		return nil, BuildErrorResponse(r, NewAppError("Client4.CreateSidebarCategoryForTeamForUser", "model.utils.decode_json.app_error", nil, err.Error(), r.StatusCode))
  5332  	}
  5333  	return cat, BuildResponse(r)
  5334  }
  5335  
  5336  func (c *Client4) GetSidebarCategoryOrderForTeamForUser(userID, teamID, etag string) ([]string, *Response) {
  5337  	route := c.GetUserCategoryRoute(userID, teamID) + "/order"
  5338  	r, err := c.DoApiGet(route, etag)
  5339  	if err != nil {
  5340  		return nil, BuildErrorResponse(r, err)
  5341  	}
  5342  	defer closeBody(r)
  5343  	return ArrayFromJson(r.Body), BuildResponse(r)
  5344  }
  5345  
  5346  func (c *Client4) UpdateSidebarCategoryOrderForTeamForUser(userID, teamID string, order []string) ([]string, *Response) {
  5347  	payload, _ := json.Marshal(order)
  5348  	route := c.GetUserCategoryRoute(userID, teamID) + "/order"
  5349  	r, err := c.doApiPutBytes(route, payload)
  5350  	if err != nil {
  5351  		return nil, BuildErrorResponse(r, err)
  5352  	}
  5353  	defer closeBody(r)
  5354  	return ArrayFromJson(r.Body), BuildResponse(r)
  5355  }
  5356  
  5357  func (c *Client4) GetSidebarCategoryForTeamForUser(userID, teamID, categoryID, etag string) (*SidebarCategoryWithChannels, *Response) {
  5358  	route := c.GetUserCategoryRoute(userID, teamID) + "/" + categoryID
  5359  	r, appErr := c.DoApiGet(route, etag)
  5360  	if appErr != nil {
  5361  		return nil, BuildErrorResponse(r, appErr)
  5362  	}
  5363  	defer closeBody(r)
  5364  	cat, err := SidebarCategoryFromJson(r.Body)
  5365  	if err != nil {
  5366  		return nil, &Response{StatusCode: http.StatusBadRequest, Error: NewAppError(c.GetUserRoute(userID), "model.client.connecting.app_error", nil, err.Error(), http.StatusForbidden)}
  5367  	}
  5368  
  5369  	return cat, BuildResponse(r)
  5370  }
  5371  
  5372  func (c *Client4) UpdateSidebarCategoryForTeamForUser(userID, teamID, categoryID string, category *SidebarCategoryWithChannels) (*SidebarCategoryWithChannels, *Response) {
  5373  	payload, _ := json.Marshal(category)
  5374  	route := c.GetUserCategoryRoute(userID, teamID) + "/" + categoryID
  5375  	r, appErr := c.doApiPutBytes(route, payload)
  5376  	if appErr != nil {
  5377  		return nil, BuildErrorResponse(r, appErr)
  5378  	}
  5379  	defer closeBody(r)
  5380  	cat, err := SidebarCategoryFromJson(r.Body)
  5381  	if err != nil {
  5382  		return nil, &Response{StatusCode: http.StatusBadRequest, Error: NewAppError(c.GetUserRoute(userID), "model.client.connecting.app_error", nil, err.Error(), http.StatusForbidden)}
  5383  	}
  5384  
  5385  	return cat, BuildResponse(r)
  5386  }
  5387  
  5388  // CheckIntegrity performs a database integrity check.
  5389  func (c *Client4) CheckIntegrity() ([]IntegrityCheckResult, *Response) {
  5390  	r, err := c.DoApiPost("/integrity", "")
  5391  	if err != nil {
  5392  		return nil, BuildErrorResponse(r, err)
  5393  	}
  5394  	defer closeBody(r)
  5395  	var results []IntegrityCheckResult
  5396  	if err := json.NewDecoder(r.Body).Decode(&results); err != nil {
  5397  		appErr := NewAppError("Api4.CheckIntegrity", "api.marshal_error", nil, err.Error(), http.StatusInternalServerError)
  5398  		return nil, BuildErrorResponse(r, appErr)
  5399  	}
  5400  	return results, BuildResponse(r)
  5401  }