func UnsafeMsgOptionEndpoint(endpoint string, update func(url.Values)) MsgOption {
	return func(config *sendConfig) error {
		config.endpoint = endpoint
		update(config.values)
		return nil
	}
}
UnsafeMsgOptionEndpoint deliver the message to the specified endpoint.
NOTE: USE AT YOUR OWN RISK: No issues relating to the use of this Option
will be supported by the library, it is subject to change without notice that
may result in compilation errors or runtime behaviour changes.
package slack
import (
	"context"
	"encoding/json"
	"net/http"
	"net/url"
	"strconv"
	"github.com/slack-go/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"`                      
	ScheduledMessageID string `json:"scheduled_message_id,omitempty"`  
	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) ScheduleMessage(channelID, postAt string, options ...MsgOption) (string, string, error) {
	respChannel, respTimestamp, _, err := api.SendMessageContext(
		context.Background(),
		channelID,
		MsgOptionSchedule(postAt),
		MsgOptionCompose(options...),
	)
	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"
	chatScheduleMessage sendMode = "chat.scheduleMessage"
	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
	blocks          Blocks
	responseType    string
	replaceOriginal bool
	deleteOriginal  bool
}
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,
			blocks:          t.blocks,
			responseType:    t.responseType,
			replaceOriginal: t.replaceOriginal,
			deleteOriginal:  t.deleteOriginal,
		}.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
	blocks          Blocks
	responseType    string
	replaceOriginal bool
	deleteOriginal  bool
}
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,
		Blocks:          t.blocks,
		ResponseType:    t.responseType,
		ReplaceOriginal: t.replaceOriginal,
		DeleteOriginal:  t.deleteOriginal,
	})
	return req, func(resp *chatResponseFull) responseParser {
		return newContentTypeParser(resp)
	}, err
}
type MsgOption func(*sendConfig) error
func MsgOptionSchedule(postAt string) MsgOption {
	return func(config *sendConfig) error {
		config.endpoint = config.apiurl + string(chatScheduleMessage)
		config.values.Add("post_at", postAt)
		return nil
	}
}
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
	}
}
func MsgOptionResponseURL(url string, responseType string) MsgOption {
	return func(config *sendConfig) error {
		config.mode = chatResponse
		config.endpoint = url
		config.responseType = responseType
		config.values.Del("ts")
		return nil
	}
}
func MsgOptionReplaceOriginal(responseURL string) MsgOption {
	return func(config *sendConfig) error {
		config.mode = chatResponse
		config.endpoint = responseURL
		config.replaceOriginal = true
		return nil
	}
}
func MsgOptionDeleteOriginal(responseURL string) MsgOption {
	return func(config *sendConfig) error {
		config.mode = chatResponse
		config.endpoint = responseURL
		config.deleteOriginal = true
		return nil
	}
}
func MsgOptionAsUser(b bool) MsgOption {
	return func(config *sendConfig) error {
		if b != DEFAULT_MESSAGE_ASUSER {
			config.values.Set("as_user", "true")
		}
		return nil
	}
}
func MsgOptionUser(userID string) MsgOption {
	return func(config *sendConfig) error {
		config.values.Set("user", userID)
		return nil
	}
}
func MsgOptionUsername(username string) MsgOption {
	return func(config *sendConfig) error {
		config.values.Set("username", username)
		return nil
	}
}
func MsgOptionText(text string, escape bool) MsgOption {
	return func(config *sendConfig) error {
		if escape {
			text = slackutilsx.EscapeMessage(text)
		}
		config.values.Add("text", text)
		return nil
	}
}
func MsgOptionAttachments(attachments ...Attachment) MsgOption {
	return func(config *sendConfig) error {
		if attachments == nil {
			return nil
		}
		config.attachments = attachments
		attachmentBytes, err := json.Marshal(attachments)
		if err == nil {
			config.values.Set("attachments", string(attachmentBytes))
		}
		return err
	}
}
func MsgOptionBlocks(blocks ...Block) MsgOption {
	return func(config *sendConfig) error {
		if blocks == nil {
			return nil
		}
		config.blocks.BlockSet = append(config.blocks.BlockSet, blocks...)
		blocks, err := json.Marshal(blocks)
		if err == nil {
			config.values.Set("blocks", string(blocks))
		}
		return err
	}
}
func MsgOptionEnableLinkUnfurl() MsgOption {
	return func(config *sendConfig) error {
		config.values.Set("unfurl_links", "true")
		return nil
	}
}
func MsgOptionDisableLinkUnfurl() MsgOption {
	return func(config *sendConfig) error {
		config.values.Set("unfurl_links", "false")
		return nil
	}
}
func MsgOptionDisableMediaUnfurl() MsgOption {
	return func(config *sendConfig) error {
		config.values.Set("unfurl_media", "false")
		return nil
	}
}
func MsgOptionDisableMarkdown() MsgOption {
	return func(config *sendConfig) error {
		config.values.Set("mrkdwn", "false")
		return nil
	}
}
func MsgOptionTS(ts string) MsgOption {
	return func(config *sendConfig) error {
		config.values.Set("thread_ts", ts)
		return nil
	}
}
func MsgOptionBroadcast() MsgOption {
	return func(config *sendConfig) error {
		config.values.Set("reply_broadcast", "true")
		return nil
	}
}
func MsgOptionCompose(options ...MsgOption) MsgOption {
	return func(c *sendConfig) error {
		for _, opt := range options {
			if err := opt(c); err != nil {
				return err
			}
		}
		return nil
	}
}
func MsgOptionParse(b bool) MsgOption {
	return func(c *sendConfig) error {
		var v string
		if b {
			v = "full"
		} else {
			v = "none"
		}
		c.values.Set("parse", v)
		return nil
	}
}
func MsgOptionIconURL(iconURL string) MsgOption {
	return func(c *sendConfig) error {
		c.values.Set("icon_url", iconURL)
		return nil
	}
}
func MsgOptionIconEmoji(iconEmoji string) MsgOption {
	return func(c *sendConfig) error {
		c.values.Set("icon_emoji", iconEmoji)
		return nil
	}
}