func (s *Session) GuildMemberMute(guildID string, userID string, mute bool) (err error) {
	data := struct {
		Mute bool `json:"mute"`
	}{mute}
	_, err = s.RequestWithBucketID("PATCH", EndpointGuildMember(guildID, userID), data, EndpointGuildMember(guildID, ""))
	return
}
GuildMemberMute server mutes a guild member
guildID   : The ID of a Guild.
userID    : The ID of a User.
mute    : boolean value for if the user should be muted
package discordgo
import (
	"bytes"
	"encoding/json"
	"errors"
	"fmt"
	"image"
	_ "image/jpeg"  
	_ "image/png"   
	"io"
	"io/ioutil"
	"log"
	"math/rand"  
	"mime/multipart"
	"net/http"
	"net/textproto"
	"net/url"
	"strconv"
	"strings"
	"time"
)
var (
	ErrJSONUnmarshal           = errors.New("json unmarshal")
	ErrStatusOffline           = errors.New("You can't set your Status to offline")
	ErrVerificationLevelBounds = errors.New("VerificationLevel out of bounds, should be between 0 and 3")
	ErrPruneDaysBounds         = errors.New("the number of days should be more than or equal to 1")
	ErrGuildNoIcon             = errors.New("guild does not have an icon set")
	ErrGuildNoSplash           = errors.New("guild does not have a splash set")
	ErrUnauthorized            = errors.New("HTTP request was unauthorized. This could be because the provided token was not a bot token. Please add \"Bot \" to the start of your token. https://discord.com/developers/docs/reference#authentication-example-bot-token-authorization-header")
)
func (s *Session) Request(method, urlStr string, data interface{}) (response []byte, err error) {
	return s.RequestWithBucketID(method, urlStr, data, strings.SplitN(urlStr, "?", 2)[0])
}
func (s *Session) RequestWithBucketID(method, urlStr string, data interface{}, bucketID string) (response []byte, err error) {
	var body []byte
	if data != nil {
		body, err = json.Marshal(data)
		if err != nil {
			return
		}
	}
	return s.request(method, urlStr, "application/json", body, bucketID, 0)
}
var globalRatelimit = make(chan struct{}, 25)
func init() {
	const shardCount = 22
	const maxRequestInterval = time.Second * shardCount / 50
	go func(ch chan struct{}, d time.Duration) {
		for {
			ch <- struct{}{}
			time.Sleep(d)
		}
	}(globalRatelimit, maxRequestInterval)
}
func (s *Session) request(method, urlStr, contentType string, b []byte, bucketID string, sequence int) (response []byte, err error) {
	if bucketID == "" {
		bucketID = strings.SplitN(urlStr, "?", 2)[0]
	}
	return s.RequestWithLockedBucket(method, urlStr, contentType, b, s.Ratelimiter.LockBucket(bucketID), sequence)
}
func (s *Session) RequestWithLockedBucket(method, urlStr, contentType string, b []byte, bucket *Bucket, sequence int) (response []byte, err error) {
	if s.Debug {
		log.Printf("API REQUEST %8s :: %s\n", method, urlStr)
		log.Printf("API REQUEST  PAYLOAD :: [%s]\n", string(b))
	}
	var instructedRetryDelay, minRetryDelay time.Duration = 0, 0
retry:
	for {
		if minRetryDelay > time.Duration(0) {
			thisRetry := minRetryDelay + instructedRetryDelay + time.Duration(rand.Int63n(int64(minRetryDelay)))
			fmt.Printf("Rate Limiting %s, retry in %v\n", urlStr, thisRetry)
			time.Sleep(thisRetry)
			instructedRetryDelay = 0
			minRetryDelay *= 2
			if minRetryDelay > 1*time.Hour {
				minRetryDelay = 1 * time.Hour
				log.Printf("API Request retry reached 1 hour: %s %s\n", method, urlStr)
			}
		} else {
			minRetryDelay = 250 * time.Millisecond
		}
		<-globalRatelimit
		req, err := http.NewRequest(method, urlStr, bytes.NewBuffer(b))
		if err != nil {
			bucket.Release(nil)
			return nil, err
		}
		if s.Token != "" {
			req.Header.Set("authorization", s.Token)
		}
		if b != nil {
			req.Header.Set("Content-Type", contentType)
		}
		req.Header.Set("User-Agent", s.UserAgent)
		if s.Debug {
			for k, v := range req.Header {
				log.Printf("API REQUEST   HEADER :: [%s] = %+v\n", k, v)
			}
		}
		resp, err := s.Client.Do(req)
		if err != nil {
			bucket.Release(nil)
			return nil, err
		}
		err = bucket.Release(resp.Header)
		if err != nil {
			err2 := resp.Body.Close()
			if err2 != nil {
				log.Println("error closing resp body:", err2)
			}
			return nil, err
		}
		response, err = ioutil.ReadAll(resp.Body)
		err2 := resp.Body.Close()
		if err2 != nil {
			log.Println("error closing resp body:", err2)
		}
		if err != nil {
			return response, err
		}
		if s.Debug {
			log.Printf("API RESPONSE  STATUS :: %s\n", resp.Status)
			for k, v := range resp.Header {
				log.Printf("API RESPONSE  HEADER :: [%s] = %+v\n", k, v)
			}
			log.Printf("API RESPONSE    BODY :: [%s]\n\n\n", response)
		}
		switch resp.StatusCode {
		case http.StatusOK:
		case http.StatusCreated:
		case http.StatusNoContent:
		case http.StatusBadGateway:
			if sequence < s.MaxRestRetries {
				s.log(LogInformational, "%s Failed (%s), Retrying...", urlStr, resp.Status)
				sequence += 1
				s.Ratelimiter.LockBucketObject(bucket)
				continue retry
			} else {
				err = fmt.Errorf("Exceeded Max retries HTTP %s, %s", resp.Status, response)
			}
		case 429:  
			rl := TooManyRequests{}
			err = json.Unmarshal(response, &rl)
			if err != nil {
				s.log(LogError, "rate limit unmarshal error, %s", err)
			}
			if rl.RetryAfter == 0 {
				rl.RetryAfter = 1 * time.Second
			}
			s.handleEvent(rateLimitEventType, &RateLimit{TooManyRequests: &rl, URL: urlStr})
			instructedRetryDelay = rl.RetryAfter
			s.Ratelimiter.LockBucketObject(bucket)
			continue retry
		case http.StatusUnauthorized:
			if strings.Index(s.Token, "Bot ") != 0 {
				s.log(LogInformational, ErrUnauthorized.Error())
				err = ErrUnauthorized
			}
			fallthrough
		default:  
			err = newRestError(req, resp, response)
		}
		return response, err
	}
}
func unmarshal(data []byte, v interface{}) error {
	err := json.Unmarshal(data, v)
	if err != nil {
		return ErrJSONUnmarshal
	}
	return nil
}
func (s *Session) Login(email, password string) (err error) {
	data := struct {
		Email    string `json:"email"`
		Password string `json:"password"`
	}{email, password}
	response, err := s.RequestWithBucketID("POST", EndpointLogin, data, EndpointLogin)
	if err != nil {
		return
	}
	temp := struct {
		Token string `json:"token"`
		MFA   bool   `json:"mfa"`
	}{}
	err = unmarshal(response, &temp)
	if err != nil {
		return
	}
	s.Token = temp.Token
	s.MFA = temp.MFA
	return
}
func (s *Session) Register(username string) (token string, err error) {
	data := struct {
		Username string `json:"username"`
	}{username}
	response, err := s.RequestWithBucketID("POST", EndpointRegister, data, EndpointRegister)
	if err != nil {
		return
	}
	temp := struct {
		Token string `json:"token"`
	}{}
	err = unmarshal(response, &temp)
	if err != nil {
		return
	}
	token = temp.Token
	return
}
func (s *Session) Logout() (err error) {
	if s.Token == "" {
		return
	}
	data := struct {
		Token string `json:"token"`
	}{s.Token}
	_, err = s.RequestWithBucketID("POST", EndpointLogout, data, EndpointLogout)
	return
}
func (s *Session) User(userID string) (st *User, err error) {
	body, err := s.RequestWithBucketID("GET", EndpointUser(userID), nil, EndpointUsers)
	if err != nil {
		return
	}
	err = unmarshal(body, &st)
	return
}
func (s *Session) UserAvatar(userID string) (img image.Image, err error) {
	u, err := s.User(userID)
	if err != nil {
		return
	}
	img, err = s.UserAvatarDecode(u)
	return
}
func (s *Session) UserAvatarDecode(u *User) (img image.Image, err error) {
	body, err := s.RequestWithBucketID("GET", EndpointUserAvatar(u.ID, u.Avatar), nil, EndpointUserAvatar("", ""))
	if err != nil {
		return
	}
	img, _, err = image.Decode(bytes.NewReader(body))
	return
}
func (s *Session) UserUpdate(email, password, username, avatar, newPassword string) (st *User, err error) {
	data := struct {
		Email       string `json:"email,omitempty"`
		Password    string `json:"password,omitempty"`
		Username    string `json:"username,omitempty"`
		Avatar      string `json:"avatar,omitempty"`
		NewPassword string `json:"new_password,omitempty"`
	}{email, password, username, avatar, newPassword}
	body, err := s.RequestWithBucketID("PATCH", EndpointUser("@me"), data, EndpointUsers)
	if err != nil {
		return
	}
	err = unmarshal(body, &st)
	return
}
func (s *Session) UserSettings() (st *Settings, err error) {
	body, err := s.RequestWithBucketID("GET", EndpointUserSettings("@me"), nil, EndpointUserSettings(""))
	if err != nil {
		return
	}
	err = unmarshal(body, &st)
	return
}
func (s *Session) UserUpdateStatus(status Status) (st *Settings, err error) {
	if status == StatusOffline {
		err = ErrStatusOffline
		return
	}
	data := struct {
		Status Status `json:"status"`
	}{status}
	body, err := s.RequestWithBucketID("PATCH", EndpointUserSettings("@me"), data, EndpointUserSettings(""))
	if err != nil {
		return
	}
	err = unmarshal(body, &st)
	return
}
func (s *Session) UserConnections() (conn []*UserConnection, err error) {
	response, err := s.RequestWithBucketID("GET", EndpointUserConnections("@me"), nil, EndpointUserConnections("@me"))
	if err != nil {
		return nil, err
	}
	err = unmarshal(response, &conn)
	if err != nil {
		return
	}
	return
}
func (s *Session) UserChannels() (st []*Channel, err error) {
	body, err := s.RequestWithBucketID("GET", EndpointUserChannels("@me"), nil, EndpointUserChannels(""))
	if err != nil {
		return
	}
	err = unmarshal(body, &st)
	return
}
func (s *Session) UserChannelCreate(recipientID string) (st *Channel, err error) {
	data := struct {
		RecipientID string `json:"recipient_id"`
	}{recipientID}
	body, err := s.RequestWithBucketID("POST", EndpointUserChannels("@me"), data, EndpointUserChannels(""))
	if err != nil {
		return
	}
	err = unmarshal(body, &st)
	return
}
func (s *Session) UserGuilds(limit int, beforeID, afterID string) (st []*UserGuild, err error) {
	v := url.Values{}
	if limit > 0 {
		v.Set("limit", strconv.Itoa(limit))
	}
	if afterID != "" {
		v.Set("after", afterID)
	}
	if beforeID != "" {
		v.Set("before", beforeID)
	}
	uri := EndpointUserGuilds("@me")
	if len(v) > 0 {
		uri += "?" + v.Encode()
	}
	body, err := s.RequestWithBucketID("GET", uri, nil, EndpointUserGuilds(""))
	if err != nil {
		return
	}
	err = unmarshal(body, &st)
	return
}
func (s *Session) UserGuildSettingsEdit(guildID string, settings *UserGuildSettingsEdit) (st *UserGuildSettings, err error) {
	body, err := s.RequestWithBucketID("PATCH", EndpointUserGuildSettings("@me", guildID), settings, EndpointUserGuildSettings("", guildID))
	if err != nil {
		return
	}
	err = unmarshal(body, &st)
	return
}
func (s *Session) UserChannelPermissions(userID, channelID string) (apermissions int64, err error) {
	apermissions, err = s.State.UserChannelPermissions(userID, channelID)
	if err == nil {
		return
	}
	channel, err := s.State.Channel(channelID)
	if err != nil || channel == nil {
		channel, err = s.Channel(channelID)
		if err != nil {
			return
		}
	}
	guild, err := s.State.Guild(channel.GuildID)
	if err != nil || guild == nil {
		guild, err = s.Guild(channel.GuildID)
		if err != nil {
			return
		}
	}
	if userID == guild.OwnerID {
		apermissions = PermissionAll
		return
	}
	member, err := s.State.Member(guild.ID, userID)
	if err != nil || member == nil {
		member, err = s.GuildMember(guild.ID, userID)
		if err != nil {
			return
		}
	}
	return memberPermissions(guild, channel, userID, member.Roles), nil
}
func memberPermissions(guild *Guild, channel *Channel, userID string, roles []string) (apermissions int64) {
	if userID == guild.OwnerID {
		apermissions = PermissionAll
		return
	}
	for _, role := range guild.Roles {
		if role.ID == guild.ID {
			apermissions |= role.Permissions
			break
		}
	}
	for _, role := range guild.Roles {
		for _, roleID := range roles {
			if role.ID == roleID {
				apermissions |= role.Permissions
				break
			}
		}
	}
	if apermissions&PermissionAdministrator == PermissionAdministrator {
		apermissions |= PermissionAll
	}
	for _, overwrite := range channel.PermissionOverwrites {
		if guild.ID == overwrite.ID {
			apermissions &= ^overwrite.Deny
			apermissions |= overwrite.Allow
			break
		}
	}
	var denies, allows int64
	for _, overwrite := range channel.PermissionOverwrites {
		for _, roleID := range roles {
			if overwrite.Type == PermissionOverwriteTypeRole && roleID == overwrite.ID {
				denies |= overwrite.Deny
				allows |= overwrite.Allow
				break
			}
		}
	}
	apermissions &= ^denies
	apermissions |= allows
	for _, overwrite := range channel.PermissionOverwrites {
		if overwrite.Type == PermissionOverwriteTypeMember && overwrite.ID == userID {
			apermissions &= ^overwrite.Deny
			apermissions |= overwrite.Allow
			break
		}
	}
	if apermissions&PermissionAdministrator == PermissionAdministrator {
		apermissions |= PermissionAllChannel
	}
	return apermissions
}
func (s *Session) Guild(guildID string) (st *Guild, err error) {
	body, err := s.RequestWithBucketID("GET", EndpointGuild(guildID), nil, EndpointGuild(guildID))
	if err != nil {
		return
	}
	err = unmarshal(body, &st)
	return
}
func (s *Session) GuildCreate(name string) (st *Guild, err error) {
	data := struct {
		Name string `json:"name"`
	}{name}
	body, err := s.RequestWithBucketID("POST", EndpointGuildCreate, data, EndpointGuildCreate)
	if err != nil {
		return
	}
	err = unmarshal(body, &st)
	return
}
func (s *Session) GuildEdit(guildID string, g GuildParams) (st *Guild, err error) {
	if g.VerificationLevel != nil {
		val := *g.VerificationLevel
		if val < 0 || val > 4 {
			err = ErrVerificationLevelBounds
			return
		}
	}
	if g.Region != "" {
		isValid := false
		regions, _ := s.VoiceRegions()
		for _, r := range regions {
			if g.Region == r.ID {
				isValid = true
			}
		}
		if !isValid {
			var valid []string
			for _, r := range regions {
				valid = append(valid, r.ID)
			}
			err = fmt.Errorf("Region not a valid region (%q)", valid)
			return
		}
	}
	body, err := s.RequestWithBucketID("PATCH", EndpointGuild(guildID), g, EndpointGuild(guildID))
	if err != nil {
		return
	}
	err = unmarshal(body, &st)
	return
}
func (s *Session) GuildDelete(guildID string) (st *Guild, err error) {
	body, err := s.RequestWithBucketID("DELETE", EndpointGuild(guildID), nil, EndpointGuild(guildID))
	if err != nil {
		return
	}
	err = unmarshal(body, &st)
	return
}
func (s *Session) GuildLeave(guildID string) (err error) {
	_, err = s.RequestWithBucketID("DELETE", EndpointUserGuild("@me", guildID), nil, EndpointUserGuild("", guildID))
	return
}
func (s *Session) GuildBans(guildID string) (st []*GuildBan, err error) {
	body, err := s.RequestWithBucketID("GET", EndpointGuildBans(guildID), nil, EndpointGuildBans(guildID))
	if err != nil {
		return
	}
	err = unmarshal(body, &st)
	return
}
func (s *Session) GuildBanCreate(guildID, userID string, days int) (err error) {
	return s.GuildBanCreateWithReason(guildID, userID, "", days)
}
func (s *Session) GuildBan(guildID, userID string) (st *GuildBan, err error) {
	body, err := s.RequestWithBucketID("GET", EndpointGuildBan(guildID, userID), nil, EndpointGuildBan(guildID, userID))
	if err != nil {
		return
	}
	err = unmarshal(body, &st)
	return
}
func (s *Session) GuildBanCreateWithReason(guildID, userID, reason string, days int) (err error) {
	uri := EndpointGuildBan(guildID, userID)
	queryParams := url.Values{}
	if days > 0 {
		queryParams.Set("delete_message_days", strconv.Itoa(days))
	}
	if reason != "" {
		queryParams.Set("reason", reason)
	}
	if len(queryParams) > 0 {
		uri += "?" + queryParams.Encode()
	}
	_, err = s.RequestWithBucketID("PUT", uri, nil, EndpointGuildBan(guildID, ""))
	return
}
func (s *Session) GuildBanDelete(guildID, userID string) (err error) {
	_, err = s.RequestWithBucketID("DELETE", EndpointGuildBan(guildID, userID), nil, EndpointGuildBan(guildID, ""))
	return
}
func (s *Session) GuildMembers(guildID string, after string, limit int) (st []*Member, err error) {
	uri := EndpointGuildMembers(guildID)
	v := url.Values{}
	if after != "" {
		v.Set("after", after)
	}
	if limit > 0 {
		v.Set("limit", strconv.Itoa(limit))
	}
	if len(v) > 0 {
		uri += "?" + v.Encode()
	}
	body, err := s.RequestWithBucketID("GET", uri, nil, EndpointGuildMembers(guildID))
	if err != nil {
		return
	}
	err = unmarshal(body, &st)
	return
}
func (s *Session) GuildMember(guildID, userID string) (st *Member, err error) {
	body, err := s.RequestWithBucketID("GET", EndpointGuildMember(guildID, userID), nil, EndpointGuildMember(guildID, ""))
	if err != nil {
		return
	}
	err = unmarshal(body, &st)
	return
}
func (s *Session) GuildMemberAdd(accessToken, guildID, userID, nick string, roles []string, mute, deaf bool) (err error) {
	data := struct {
		AccessToken string   `json:"access_token"`
		Nick        string   `json:"nick,omitempty"`
		Roles       []string `json:"roles,omitempty"`
		Mute        bool     `json:"mute,omitempty"`
		Deaf        bool     `json:"deaf,omitempty"`
	}{accessToken, nick, roles, mute, deaf}
	_, err = s.RequestWithBucketID("PUT", EndpointGuildMember(guildID, userID), data, EndpointGuildMember(guildID, ""))
	if err != nil {
		return err
	}
	return err
}
func (s *Session) GuildMemberDelete(guildID, userID string) (err error) {
	return s.GuildMemberDeleteWithReason(guildID, userID, "")
}
func (s *Session) GuildMemberDeleteWithReason(guildID, userID, reason string) (err error) {
	uri := EndpointGuildMember(guildID, userID)
	if reason != "" {
		uri += "?reason=" + url.QueryEscape(reason)
	}
	_, err = s.RequestWithBucketID("DELETE", uri, nil, EndpointGuildMember(guildID, ""))
	return
}
func (s *Session) GuildMemberEdit(guildID, userID string, roles []string) (err error) {
	data := struct {
		Roles []string `json:"roles"`
	}{roles}
	_, err = s.RequestWithBucketID("PATCH", EndpointGuildMember(guildID, userID), data, EndpointGuildMember(guildID, ""))
	return
}
func (s *Session) GuildMemberMove(guildID string, userID string, channelID *string) (err error) {
	data := struct {
		ChannelID *string `json:"channel_id"`
	}{channelID}
	_, err = s.RequestWithBucketID("PATCH", EndpointGuildMember(guildID, userID), data, EndpointGuildMember(guildID, ""))
	return
}
func (s *Session) GuildMemberNickname(guildID, userID, nickname string) (err error) {
	data := struct {
		Nick string `json:"nick"`
	}{nickname}
	if userID == "@me" {
		userID += "/nick"
	}
	_, err = s.RequestWithBucketID("PATCH", EndpointGuildMember(guildID, userID), data, EndpointGuildMember(guildID, ""))
	return
}