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