func (c *Client4) GetUserByUsername(userName, etag string) (*User, *Response) {
	if r, err := c.DoApiGet(c.GetUserByUsernameRoute(userName), etag); err != nil {
		return nil, BuildErrorResponse(r, err)
	} else {
		defer closeBody(r)
		return UserFromJson(r.Body), BuildResponse(r)
	}
}
GetUserByUsername returns a user based on the provided user name string.
package model
import (
	"bytes"
	"fmt"
	"io"
	"io/ioutil"
	"mime/multipart"
	"net/http"
	"net/url"
	"strconv"
	"strings"
	"time"
)
const (
	HEADER_REQUEST_ID         = "X-Request-ID"
	HEADER_VERSION_ID         = "X-Version-ID"
	HEADER_CLUSTER_ID         = "X-Cluster-ID"
	HEADER_ETAG_SERVER        = "ETag"
	HEADER_ETAG_CLIENT        = "If-None-Match"
	HEADER_FORWARDED          = "X-Forwarded-For"
	HEADER_REAL_IP            = "X-Real-IP"
	HEADER_FORWARDED_PROTO    = "X-Forwarded-Proto"
	HEADER_TOKEN              = "token"
	HEADER_BEARER             = "BEARER"
	HEADER_AUTH               = "Authorization"
	HEADER_REQUESTED_WITH     = "X-Requested-With"
	HEADER_REQUESTED_WITH_XML = "XMLHttpRequest"
	STATUS                    = "status"
	STATUS_OK                 = "OK"
	STATUS_FAIL               = "FAIL"
	STATUS_REMOVE             = "REMOVE"
	CLIENT_DIR = "client"
	API_URL_SUFFIX_V1 = "/api/v1"
	API_URL_SUFFIX_V4 = "/api/v4"
	API_URL_SUFFIX    = API_URL_SUFFIX_V4
)
type Response struct {
	StatusCode    int
	Error         *AppError
	RequestId     string
	Etag          string
	ServerVersion string
	Header        http.Header
}
type Client4 struct {
	Url        string        
	ApiUrl     string        
	HttpClient *http.Client  
	AuthToken  string
	AuthType   string
	HttpHeader map[string]string  
}
func closeBody(r *http.Response) {
	if r.Body != nil {
		ioutil.ReadAll(r.Body)
		r.Body.Close()
	}
}
func (c *Client4) Must(result interface{}, resp *Response) interface{} {
	if resp.Error != nil {
		time.Sleep(time.Second)
		panic(resp.Error)
	}
	return result
}
func NewAPIv4Client(url string) *Client4 {
	return &Client4{url, url + API_URL_SUFFIX, &http.Client{}, "", "", map[string]string{}}
}
func BuildErrorResponse(r *http.Response, err *AppError) *Response {
	var statusCode int
	var header http.Header
	if r != nil {
		statusCode = r.StatusCode
		header = r.Header
	} else {
		statusCode = 0
		header = make(http.Header)
	}
	return &Response{
		StatusCode: statusCode,
		Error:      err,
		Header:     header,
	}
}
func BuildResponse(r *http.Response) *Response {
	return &Response{
		StatusCode:    r.StatusCode,
		RequestId:     r.Header.Get(HEADER_REQUEST_ID),
		Etag:          r.Header.Get(HEADER_ETAG_SERVER),
		ServerVersion: r.Header.Get(HEADER_VERSION_ID),
		Header:        r.Header,
	}
}
func (c *Client4) MockSession(sessionToken string) {
	c.AuthToken = sessionToken
	c.AuthType = HEADER_BEARER
}
func (c *Client4) SetOAuthToken(token string) {
	c.AuthToken = token
	c.AuthType = HEADER_TOKEN
}
func (c *Client4) ClearOAuthToken() {
	c.AuthToken = ""
	c.AuthType = HEADER_BEARER
}
func (c *Client4) GetUsersRoute() string {
	return fmt.Sprintf("/users")
}
func (c *Client4) GetUserRoute(userId string) string {
	return fmt.Sprintf(c.GetUsersRoute()+"/%v", userId)
}
func (c *Client4) GetUserAccessTokensRoute() string {
	return fmt.Sprintf(c.GetUsersRoute() + "/tokens")
}
func (c *Client4) GetUserAccessTokenRoute(tokenId string) string {
	return fmt.Sprintf(c.GetUsersRoute()+"/tokens/%v", tokenId)
}
func (c *Client4) GetUserByUsernameRoute(userName string) string {
	return fmt.Sprintf(c.GetUsersRoute()+"/username/%v", userName)
}
func (c *Client4) GetUserByEmailRoute(email string) string {
	return fmt.Sprintf(c.GetUsersRoute()+"/email/%v", email)
}
func (c *Client4) GetTeamsRoute() string {
	return fmt.Sprintf("/teams")
}
func (c *Client4) GetTeamRoute(teamId string) string {
	return fmt.Sprintf(c.GetTeamsRoute()+"/%v", teamId)
}
func (c *Client4) GetTeamAutoCompleteCommandsRoute(teamId string) string {
	return fmt.Sprintf(c.GetTeamsRoute()+"/%v/commands/autocomplete", teamId)
}
func (c *Client4) GetTeamByNameRoute(teamName string) string {
	return fmt.Sprintf(c.GetTeamsRoute()+"/name/%v", teamName)
}
func (c *Client4) GetTeamMemberRoute(teamId, userId string) string {
	return fmt.Sprintf(c.GetTeamRoute(teamId)+"/members/%v", userId)
}
func (c *Client4) GetTeamMembersRoute(teamId string) string {
	return fmt.Sprintf(c.GetTeamRoute(teamId) + "/members")
}
func (c *Client4) GetTeamStatsRoute(teamId string) string {
	return fmt.Sprintf(c.GetTeamRoute(teamId) + "/stats")
}
func (c *Client4) GetTeamImportRoute(teamId string) string {
	return fmt.Sprintf(c.GetTeamRoute(teamId) + "/import")
}
func (c *Client4) GetChannelsRoute() string {
	return fmt.Sprintf("/channels")
}
func (c *Client4) GetChannelsForTeamRoute(teamId string) string {
	return fmt.Sprintf(c.GetTeamRoute(teamId) + "/channels")
}
func (c *Client4) GetChannelRoute(channelId string) string {
	return fmt.Sprintf(c.GetChannelsRoute()+"/%v", channelId)
}
func (c *Client4) GetChannelByNameRoute(channelName, teamId string) string {
	return fmt.Sprintf(c.GetTeamRoute(teamId)+"/channels/name/%v", channelName)
}
func (c *Client4) GetChannelByNameForTeamNameRoute(channelName, teamName string) string {
	return fmt.Sprintf(c.GetTeamByNameRoute(teamName)+"/channels/name/%v", channelName)
}
func (c *Client4) GetChannelMembersRoute(channelId string) string {
	return fmt.Sprintf(c.GetChannelRoute(channelId) + "/members")
}
func (c *Client4) GetChannelMemberRoute(channelId, userId string) string {
	return fmt.Sprintf(c.GetChannelMembersRoute(channelId)+"/%v", userId)
}
func (c *Client4) GetPostsRoute() string {
	return fmt.Sprintf("/posts")
}
func (c *Client4) GetPostsEphemeralRoute() string {
	return fmt.Sprintf("/posts/ephemeral")
}
func (c *Client4) GetConfigRoute() string {
	return fmt.Sprintf("/config")
}
func (c *Client4) GetLicenseRoute() string {
	return fmt.Sprintf("/license")
}
func (c *Client4) GetPostRoute(postId string) string {
	return fmt.Sprintf(c.GetPostsRoute()+"/%v", postId)
}
func (c *Client4) GetFilesRoute() string {
	return fmt.Sprintf("/files")
}
func (c *Client4) GetFileRoute(fileId string) string {
	return fmt.Sprintf(c.GetFilesRoute()+"/%v", fileId)
}
func (c *Client4) GetPluginsRoute() string {
	return fmt.Sprintf("/plugins")
}
func (c *Client4) GetPluginRoute(pluginId string) string {
	return fmt.Sprintf(c.GetPluginsRoute()+"/%v", pluginId)
}
func (c *Client4) GetSystemRoute() string {
	return fmt.Sprintf("/system")
}
func (c *Client4) GetTestEmailRoute() string {
	return fmt.Sprintf("/email/test")
}
func (c *Client4) GetTestS3Route() string {
	return fmt.Sprintf("/file/s3_test")
}
func (c *Client4) GetDatabaseRoute() string {
	return fmt.Sprintf("/database")
}
func (c *Client4) GetCacheRoute() string {
	return fmt.Sprintf("/caches")
}
func (c *Client4) GetClusterRoute() string {
	return fmt.Sprintf("/cluster")
}
func (c *Client4) GetIncomingWebhooksRoute() string {
	return fmt.Sprintf("/hooks/incoming")
}
func (c *Client4) GetIncomingWebhookRoute(hookID string) string {
	return fmt.Sprintf(c.GetIncomingWebhooksRoute()+"/%v", hookID)
}
func (c *Client4) GetComplianceReportsRoute() string {
	return fmt.Sprintf("/compliance/reports")
}
func (c *Client4) GetComplianceReportRoute(reportId string) string {
	return fmt.Sprintf("/compliance/reports/%v", reportId)
}
func (c *Client4) GetOutgoingWebhooksRoute() string {
	return fmt.Sprintf("/hooks/outgoing")
}
func (c *Client4) GetOutgoingWebhookRoute(hookID string) string {
	return fmt.Sprintf(c.GetOutgoingWebhooksRoute()+"/%v", hookID)
}
func (c *Client4) GetPreferencesRoute(userId string) string {
	return fmt.Sprintf(c.GetUserRoute(userId) + "/preferences")
}
func (c *Client4) GetUserStatusRoute(userId string) string {
	return fmt.Sprintf(c.GetUserRoute(userId) + "/status")
}
func (c *Client4) GetUserStatusesRoute() string {
	return fmt.Sprintf(c.GetUsersRoute() + "/status")
}
func (c *Client4) GetSamlRoute() string {
	return fmt.Sprintf("/saml")
}
func (c *Client4) GetLdapRoute() string {
	return fmt.Sprintf("/ldap")
}
func (c *Client4) GetBrandRoute() string {
	return fmt.Sprintf("/brand")
}
func (c *Client4) GetDataRetentionRoute() string {
	return fmt.Sprintf("/data_retention")
}
func (c *Client4) GetElasticsearchRoute() string {
	return fmt.Sprintf("/elasticsearch")
}
func (c *Client4) GetCommandsRoute() string {
	return fmt.Sprintf("/commands")
}
func (c *Client4) GetCommandRoute(commandId string) string {
	return fmt.Sprintf(c.GetCommandsRoute()+"/%v", commandId)
}
func (c *Client4) GetEmojisRoute() string {
	return fmt.Sprintf("/emoji")
}
func (c *Client4) GetEmojiRoute(emojiId string) string {
	return fmt.Sprintf(c.GetEmojisRoute()+"/%v", emojiId)
}
func (c *Client4) GetEmojiByNameRoute(name string) string {
	return fmt.Sprintf(c.GetEmojisRoute()+"/name/%v", name)
}
func (c *Client4) GetReactionsRoute() string {
	return fmt.Sprintf("/reactions")
}
func (c *Client4) GetOAuthAppsRoute() string {
	return fmt.Sprintf("/oauth/apps")
}
func (c *Client4) GetOAuthAppRoute(appId string) string {
	return fmt.Sprintf("/oauth/apps/%v", appId)
}
func (c *Client4) GetOpenGraphRoute() string {
	return fmt.Sprintf("/opengraph")
}
func (c *Client4) GetJobsRoute() string {
	return fmt.Sprintf("/jobs")
}
func (c *Client4) GetRolesRoute() string {
	return fmt.Sprintf("/roles")
}
func (c *Client4) GetSchemesRoute() string {
	return fmt.Sprintf("/schemes")
}
func (c *Client4) GetSchemeRoute(id string) string {
	return c.GetSchemesRoute() + fmt.Sprintf("/%v", id)
}
func (c *Client4) GetAnalyticsRoute() string {
	return fmt.Sprintf("/analytics")
}
func (c *Client4) GetTimezonesRoute() string {
	return fmt.Sprintf(c.GetSystemRoute() + "/timezones")
}
func (c *Client4) GetChannelSchemeRoute(channelId string) string {
	return fmt.Sprintf(c.GetChannelsRoute()+"/%v/scheme", channelId)
}
func (c *Client4) GetTeamSchemeRoute(teamId string) string {
	return fmt.Sprintf(c.GetTeamsRoute()+"/%v/scheme", teamId)
}
func (c *Client4) GetTotalUsersStatsRoute() string {
	return fmt.Sprintf(c.GetUsersRoute() + "/stats")
}
func (c *Client4) GetRedirectLocationRoute() string {
	return fmt.Sprintf("/redirect_location")
}
func (c *Client4) GetRegisterTermsOfServiceRoute(userId string) string {
	return c.GetUserRoute(userId) + "/terms_of_service"
}
func (c *Client4) GetTermsOfServiceRoute() string {
	return "/terms_of_service"
}
func (c *Client4) DoApiGet(url string, etag string) (*http.Response, *AppError) {
	return c.DoApiRequest(http.MethodGet, c.ApiUrl+url, "", etag)
}
func (c *Client4) DoApiPost(url string, data string) (*http.Response, *AppError) {
	return c.DoApiRequest(http.MethodPost, c.ApiUrl+url, data, "")
}
func (c *Client4) DoApiPut(url string, data string) (*http.Response, *AppError) {
	return c.DoApiRequest(http.MethodPut, c.ApiUrl+url, data, "")
}
func (c *Client4) DoApiDelete(url string) (*http.Response, *AppError) {
	return c.DoApiRequest(http.MethodDelete, c.ApiUrl+url, "", "")
}
func (c *Client4) DoApiRequest(method, url, data, etag string) (*http.Response, *AppError) {
	rq, _ := http.NewRequest(method, url, strings.NewReader(data))
	if len(etag) > 0 {
		rq.Header.Set(HEADER_ETAG_CLIENT, etag)
	}
	if len(c.AuthToken) > 0 {
		rq.Header.Set(HEADER_AUTH, c.AuthType+" "+c.AuthToken)
	}
	if c.HttpHeader != nil && len(c.HttpHeader) > 0 {
		for k, v := range c.HttpHeader {
			rq.Header.Set(k, v)
		}
	}
	if rp, err := c.HttpClient.Do(rq); err != nil || rp == nil {
		return nil, NewAppError(url, "model.client.connecting.app_error", nil, err.Error(), 0)
	} else if rp.StatusCode == 304 {
		return rp, nil
	} else if rp.StatusCode >= 300 {
		defer closeBody(rp)
		return rp, AppErrorFromJson(rp.Body)
	} else {
		return rp, nil
	}
}
func (c *Client4) DoUploadFile(url string, data []byte, contentType string) (*FileUploadResponse, *Response) {
	rq, _ := http.NewRequest("POST", c.ApiUrl+url, bytes.NewReader(data))
	rq.Header.Set("Content-Type", contentType)
	if len(c.AuthToken) > 0 {
		rq.Header.Set(HEADER_AUTH, c.AuthType+" "+c.AuthToken)
	}
	if rp, err := c.HttpClient.Do(rq); err != nil || rp == nil {
		return nil, BuildErrorResponse(rp, NewAppError(url, "model.client.connecting.app_error", nil, err.Error(), 0))
	} else {
		defer closeBody(rp)
		if rp.StatusCode >= 300 {
			return nil, BuildErrorResponse(rp, AppErrorFromJson(rp.Body))
		} else {
			return FileUploadResponseFromJson(rp.Body), BuildResponse(rp)
		}
	}
}
func (c *Client4) DoEmojiUploadFile(url string, data []byte, contentType string) (*Emoji, *Response) {
	rq, _ := http.NewRequest("POST", c.ApiUrl+url, bytes.NewReader(data))
	rq.Header.Set("Content-Type", contentType)
	if len(c.AuthToken) > 0 {
		rq.Header.Set(HEADER_AUTH, c.AuthType+" "+c.AuthToken)
	}
	if rp, err := c.HttpClient.Do(rq); err != nil || rp == nil {
		return nil, BuildErrorResponse(rp, NewAppError(url, "model.client.connecting.app_error", nil, err.Error(), 0))
	} else {
		defer closeBody(rp)
		if rp.StatusCode >= 300 {
			return nil, BuildErrorResponse(rp, AppErrorFromJson(rp.Body))
		} else {
			return EmojiFromJson(rp.Body), BuildResponse(rp)
		}
	}
}
func (c *Client4) DoUploadImportTeam(url string, data []byte, contentType string) (map[string]string, *Response) {
	rq, _ := http.NewRequest("POST", c.ApiUrl+url, bytes.NewReader(data))
	rq.Header.Set("Content-Type", contentType)
	if len(c.AuthToken) > 0 {
		rq.Header.Set(HEADER_AUTH, c.AuthType+" "+c.AuthToken)
	}
	if rp, err := c.HttpClient.Do(rq); err != nil || rp == nil {
		return nil, BuildErrorResponse(rp, NewAppError(url, "model.client.connecting.app_error", nil, err.Error(), 0))
	} else {
		defer closeBody(rp)
		if rp.StatusCode >= 300 {
			return nil, BuildErrorResponse(rp, AppErrorFromJson(rp.Body))
		} else {
			return MapFromJson(rp.Body), BuildResponse(rp)
		}
	}
}
func CheckStatusOK(r *http.Response) bool {
	m := MapFromJson(r.Body)
	defer closeBody(r)
	if m != nil && m[STATUS] == STATUS_OK {
		return true
	}
	return false
}
func (c *Client4) LoginById(id string, password string) (*User, *Response) {
	m := make(map[string]string)
	m["id"] = id
	m["password"] = password
	return c.login(m)
}
func (c *Client4) Login(loginId string, password string) (*User, *Response) {
	m := make(map[string]string)
	m["login_id"] = loginId
	m["password"] = password
	return c.login(m)
}
func (c *Client4) LoginByLdap(loginId string, password string) (*User, *Response) {
	m := make(map[string]string)
	m["login_id"] = loginId
	m["password"] = password
	m["ldap_only"] = "true"
	return c.login(m)
}
func (c *Client4) LoginWithDevice(loginId string, password string, deviceId string) (*User, *Response) {
	m := make(map[string]string)
	m["login_id"] = loginId
	m["password"] = password
	m["device_id"] = deviceId
	return c.login(m)
}
func (c *Client4) login(m map[string]string) (*User, *Response) {
	if r, err := c.DoApiPost("/users/login", MapToJson(m)); err != nil {
		return nil, BuildErrorResponse(r, err)
	} else {
		c.AuthToken = r.Header.Get(HEADER_TOKEN)
		c.AuthType = HEADER_BEARER
		defer closeBody(r)
		return UserFromJson(r.Body), BuildResponse(r)
	}
}
func (c *Client4) Logout() (bool, *Response) {
	if r, err := c.DoApiPost("/users/logout", ""); err != nil {
		return false, BuildErrorResponse(r, err)
	} else {
		c.AuthToken = ""
		c.AuthType = HEADER_BEARER
		defer closeBody(r)
		return CheckStatusOK(r), BuildResponse(r)
	}
}
func (c *Client4) SwitchAccountType(switchRequest *SwitchRequest) (string, *Response) {
	if r, err := c.DoApiPost(c.GetUsersRoute()+"/login/switch", switchRequest.ToJson()); err != nil {
		return "", BuildErrorResponse(r, err)
	} else {
		defer closeBody(r)
		return MapFromJson(r.Body)["follow_link"], BuildResponse(r)
	}
}
func (c *Client4) CreateUser(user *User) (*User, *Response) {
	if r, err := c.DoApiPost(c.GetUsersRoute(), user.ToJson()); err != nil {
		return nil, BuildErrorResponse(r, err)
	} else {
		defer closeBody(r)
		return UserFromJson(r.Body), BuildResponse(r)
	}
}
func (c *Client4) CreateUserWithToken(user *User, tokenId string) (*User, *Response) {
	var query string
	if tokenId != "" {
		query = fmt.Sprintf("?t=%v", tokenId)
	} else {
		err := NewAppError("MissingHashOrData", "api.user.create_user.missing_token.app_error", nil, "", http.StatusBadRequest)
		return nil, &Response{StatusCode: err.StatusCode, Error: err}
	}
	if r, err := c.DoApiPost(c.GetUsersRoute()+query, user.ToJson()); err != nil {
		return nil, BuildErrorResponse(r, err)
	} else {
		defer closeBody(r)
		return UserFromJson(r.Body), BuildResponse(r)
	}
}
func (c *Client4) CreateUserWithInviteId(user *User, inviteId string) (*User, *Response) {
	var query string
	if inviteId != "" {
		query = fmt.Sprintf("?iid=%v", url.QueryEscape(inviteId))
	} else {
		err := NewAppError("MissingInviteId", "api.user.create_user.missing_invite_id.app_error", nil, "", http.StatusBadRequest)
		return nil, &Response{StatusCode: err.StatusCode, Error: err}
	}
	if r, err := c.DoApiPost(c.GetUsersRoute()+query, user.ToJson()); err != nil {
		return nil, BuildErrorResponse(r, err)
	} else {
		defer closeBody(r)
		return UserFromJson(r.Body), BuildResponse(r)
	}
}
func (c *Client4) GetMe(etag string) (*User, *Response) {
	if r, err := c.DoApiGet(c.GetUserRoute(ME), etag); err != nil {
		return nil, BuildErrorResponse(r, err)
	} else {
		defer closeBody(r)
		return UserFromJson(r.Body), BuildResponse(r)
	}
}
func (c *Client4) GetUser(userId, etag string) (*User, *Response) {
	if r, err := c.DoApiGet(c.GetUserRoute(userId), etag); err != nil {
		return nil, BuildErrorResponse(r, err)
	} else {
		defer closeBody(r)
		return UserFromJson(r.Body), BuildResponse(r)
	}
}