func MsgOptionResponseURL(url string, rt string) MsgOption {
	return func(config *sendConfig) error {
		config.mode = chatResponse
		config.endpoint = url
		config.responseType = rt
		config.values.Del("ts")
		return nil
	}
}
MsgOptionResponseURL supplies a url to use as the endpoint.
package slack
import (
	"context"
	"encoding/json"
	"net/http"
	"net/url"
	"github.com/nlopes/slack/slackutilsx"
)
const (
	DEFAULT_MESSAGE_USERNAME         = ""
	DEFAULT_MESSAGE_REPLY_BROADCAST  = false
	DEFAULT_MESSAGE_ASUSER           = false
	DEFAULT_MESSAGE_PARSE            = ""
	DEFAULT_MESSAGE_THREAD_TIMESTAMP = ""
	DEFAULT_MESSAGE_LINK_NAMES       = 0
	DEFAULT_MESSAGE_UNFURL_LINKS     = false
	DEFAULT_MESSAGE_UNFURL_MEDIA     = true
	DEFAULT_MESSAGE_ICON_URL         = ""
	DEFAULT_MESSAGE_ICON_EMOJI       = ""
	DEFAULT_MESSAGE_MARKDOWN         = true
	DEFAULT_MESSAGE_ESCAPE_TEXT      = true
)
type chatResponseFull struct {
	Channel          string `json:"channel"`
	Timestamp        string `json:"ts"`          
	MessageTimeStamp string `json:"message_ts"`  
	Text             string `json:"text"`
	SlackResponse
}
func (c chatResponseFull) getMessageTimestamp() string {
	if len(c.Timestamp) > 0 {
		return c.Timestamp
	}
	return c.MessageTimeStamp
}
type PostMessageParameters struct {
	Username        string `json:"username"`
	AsUser          bool   `json:"as_user"`
	Parse           string `json:"parse"`
	ThreadTimestamp string `json:"thread_ts"`
	ReplyBroadcast  bool   `json:"reply_broadcast"`
	LinkNames       int    `json:"link_names"`
	UnfurlLinks     bool   `json:"unfurl_links"`
	UnfurlMedia     bool   `json:"unfurl_media"`
	IconURL         string `json:"icon_url"`
	IconEmoji       string `json:"icon_emoji"`
	Markdown        bool   `json:"mrkdwn,omitempty"`
	EscapeText      bool   `json:"escape_text"`
	Channel string `json:"channel"`
	User    string `json:"user"`
}
func NewPostMessageParameters() PostMessageParameters {
	return PostMessageParameters{
		Username:        DEFAULT_MESSAGE_USERNAME,
		User:            DEFAULT_MESSAGE_USERNAME,
		AsUser:          DEFAULT_MESSAGE_ASUSER,
		Parse:           DEFAULT_MESSAGE_PARSE,
		ThreadTimestamp: DEFAULT_MESSAGE_THREAD_TIMESTAMP,
		LinkNames:       DEFAULT_MESSAGE_LINK_NAMES,
		UnfurlLinks:     DEFAULT_MESSAGE_UNFURL_LINKS,
		UnfurlMedia:     DEFAULT_MESSAGE_UNFURL_MEDIA,
		IconURL:         DEFAULT_MESSAGE_ICON_URL,
		IconEmoji:       DEFAULT_MESSAGE_ICON_EMOJI,
		Markdown:        DEFAULT_MESSAGE_MARKDOWN,
		EscapeText:      DEFAULT_MESSAGE_ESCAPE_TEXT,
	}
}
func (api *Client) DeleteMessage(channel, messageTimestamp string) (string, string, error) {
	respChannel, respTimestamp, _, err := api.SendMessageContext(context.Background(), channel, MsgOptionDelete(messageTimestamp))
	return respChannel, respTimestamp, err
}
func (api *Client) DeleteMessageContext(ctx context.Context, channel, messageTimestamp string) (string, string, error) {
	respChannel, respTimestamp, _, err := api.SendMessageContext(ctx, channel, MsgOptionDelete(messageTimestamp))
	return respChannel, respTimestamp, err
}
func (api *Client) PostMessage(channelID string, options ...MsgOption) (string, string, error) {
	respChannel, respTimestamp, _, err := api.SendMessageContext(
		context.Background(),
		channelID,
		MsgOptionPost(),
		MsgOptionCompose(options...),
	)
	return respChannel, respTimestamp, err
}
func (api *Client) PostMessageContext(ctx context.Context, channelID string, options ...MsgOption) (string, string, error) {
	respChannel, respTimestamp, _, err := api.SendMessageContext(
		ctx,
		channelID,
		MsgOptionPost(),
		MsgOptionCompose(options...),
	)
	return respChannel, respTimestamp, err
}
func (api *Client) PostEphemeral(channelID, userID string, options ...MsgOption) (string, error) {
	return api.PostEphemeralContext(
		context.Background(),
		channelID,
		userID,
		options...,
	)
}
func (api *Client) PostEphemeralContext(ctx context.Context, channelID, userID string, options ...MsgOption) (timestamp string, err error) {
	_, timestamp, _, err = api.SendMessageContext(ctx, channelID, MsgOptionPostEphemeral(userID), MsgOptionCompose(options...))
	return timestamp, err
}
func (api *Client) UpdateMessage(channelID, timestamp string, options ...MsgOption) (string, string, string, error) {
	return api.SendMessageContext(context.Background(), channelID, MsgOptionUpdate(timestamp), MsgOptionCompose(options...))
}
func (api *Client) UpdateMessageContext(ctx context.Context, channelID, timestamp string, options ...MsgOption) (string, string, string, error) {
	return api.SendMessageContext(ctx, channelID, MsgOptionUpdate(timestamp), MsgOptionCompose(options...))
}
func (api *Client) UnfurlMessage(channelID, timestamp string, unfurls map[string]Attachment, options ...MsgOption) (string, string, string, error) {
	return api.SendMessageContext(context.Background(), channelID, MsgOptionUnfurl(timestamp, unfurls), MsgOptionCompose(options...))
}
func (api *Client) SendMessage(channel string, options ...MsgOption) (string, string, string, error) {
	return api.SendMessageContext(context.Background(), channel, options...)
}
func (api *Client) SendMessageContext(ctx context.Context, channelID string, options ...MsgOption) (_channel string, _timestamp string, _text string, err error) {
	var (
		req      *http.Request
		parser   func(*chatResponseFull) responseParser
		response chatResponseFull
	)
	if req, parser, err = buildSender(api.endpoint, options...).BuildRequest(api.token, channelID); err != nil {
		return "", "", "", err
	}
	if err = doPost(ctx, api.httpclient, req, parser(&response), api); err != nil {
		return "", "", "", err
	}
	return response.Channel, response.getMessageTimestamp(), response.Text, response.Err()
}
func UnsafeApplyMsgOptions(token, channel, apiurl string, options ...MsgOption) (string, url.Values, error) {
	config, err := applyMsgOptions(token, channel, apiurl, options...)
	return config.endpoint, config.values, err
}
func applyMsgOptions(token, channel, apiurl string, options ...MsgOption) (sendConfig, error) {
	config := sendConfig{
		apiurl:   apiurl,
		endpoint: apiurl + string(chatPostMessage),
		values: url.Values{
			"token":   {token},
			"channel": {channel},
		},
	}
	for _, opt := range options {
		if err := opt(&config); err != nil {
			return config, err
		}
	}
	return config, nil
}
func buildSender(apiurl string, options ...MsgOption) sendConfig {
	return sendConfig{
		apiurl:  apiurl,
		options: options,
	}
}
type sendMode string
const (
	chatUpdate        sendMode = "chat.update"
	chatPostMessage   sendMode = "chat.postMessage"
	chatDelete        sendMode = "chat.delete"
	chatPostEphemeral sendMode = "chat.postEphemeral"
	chatResponse      sendMode = "chat.responseURL"
	chatMeMessage     sendMode = "chat.meMessage"
	chatUnfurl        sendMode = "chat.unfurl"
)
type sendConfig struct {
	apiurl       string
	options      []MsgOption
	mode         sendMode
	endpoint     string
	values       url.Values
	attachments  []Attachment
	responseType string
}
func (t sendConfig) BuildRequest(token, channelID string) (req *http.Request, _ func(*chatResponseFull) responseParser, err error) {
	if t, err = applyMsgOptions(token, channelID, t.apiurl, t.options...); err != nil {
		return nil, nil, err
	}
	switch t.mode {
	case chatResponse:
		return responseURLSender{
			endpoint:     t.endpoint,
			values:       t.values,
			attachments:  t.attachments,
			responseType: t.responseType,
		}.BuildRequest()
	default:
		return formSender{endpoint: t.endpoint, values: t.values}.BuildRequest()
	}
}
type formSender struct {
	endpoint string
	values   url.Values
}
func (t formSender) BuildRequest() (*http.Request, func(*chatResponseFull) responseParser, error) {
	req, err := formReq(t.endpoint, t.values)
	return req, func(resp *chatResponseFull) responseParser {
		return newJSONParser(resp)
	}, err
}
type responseURLSender struct {
	endpoint     string
	values       url.Values
	attachments  []Attachment
	responseType string
}
func (t responseURLSender) BuildRequest() (*http.Request, func(*chatResponseFull) responseParser, error) {
	req, err := jsonReq(t.endpoint, Msg{
		Text:         t.values.Get("text"),
		Timestamp:    t.values.Get("ts"),
		Attachments:  t.attachments,
		ResponseType: t.responseType,
	})
	return req, func(resp *chatResponseFull) responseParser {
		return newContentTypeParser(resp)
	}, err
}
type MsgOption func(*sendConfig) error
func MsgOptionPost() MsgOption {
	return func(config *sendConfig) error {
		config.endpoint = config.apiurl + string(chatPostMessage)
		config.values.Del("ts")
		return nil
	}
}
func MsgOptionPostEphemeral(userID string) MsgOption {
	return func(config *sendConfig) error {
		config.endpoint = config.apiurl + string(chatPostEphemeral)
		MsgOptionUser(userID)(config)
		config.values.Del("ts")
		return nil
	}
}
func MsgOptionMeMessage() MsgOption {
	return func(config *sendConfig) error {
		config.endpoint = config.apiurl + string(chatMeMessage)
		return nil
	}
}
func MsgOptionUpdate(timestamp string) MsgOption {
	return func(config *sendConfig) error {
		config.endpoint = config.apiurl + string(chatUpdate)
		config.values.Add("ts", timestamp)
		return nil
	}
}
func MsgOptionDelete(timestamp string) MsgOption {
	return func(config *sendConfig) error {
		config.endpoint = config.apiurl + string(chatDelete)
		config.values.Add("ts", timestamp)
		return nil
	}
}
func MsgOptionUnfurl(timestamp string, unfurls map[string]Attachment) MsgOption {
	return func(config *sendConfig) error {
		config.endpoint = config.apiurl + string(chatUnfurl)
		config.values.Add("ts", timestamp)
		unfurlsStr, err := json.Marshal(unfurls)
		if err == nil {
			config.values.Add("unfurls", string(unfurlsStr))
		}
		return err
	}
}