Repository: slack-go/slack
Pull request #696 (2020-04-09 15:55:22)

Add support for `user_team` and `source_team` in `app_mention` and `message` events
#### Summary

* Isse #695 
* Adds support for `user_team` and `source_team` in `app_mention` and `message` events.


Patch:
diff --git a/Makefile b/Makefile
index 7279640..1c64747 100644
--- a/Makefile
+++ b/Makefile
@@ -25,12 +25,12 @@ lint:
 	@go vet .
 
 test:
-	@go test -v -count=1 -timeout 300s -short ./...
+	@go test -count=1 -timeout 300s -short .
 
 test-race:
-	@go test -v -count=1 -timeout 300s -short -race ./...
+	@go test -count=1 -timeout 300s -short -race .
 
 test-integration:
-	@go test -v -count=1 -timeout 600s ./...
+	@go test -count=1 -timeout 600s .
 
 pr-prep: fmt lint test-race test-integration
diff --git a/auth.go b/auth.go
index f4f7f00..dc1dbcd 100644
--- a/auth.go
+++ b/auth.go
@@ -27,7 +27,7 @@ func (api *Client) SendAuthRevoke(token string) (*AuthRevokeResponse, error) {
 	return api.SendAuthRevokeContext(context.Background(), token)
 }
 
-// SendAuthRevokeContext will send a revocation request for our token to api.revoke with context
+// SendAuthRevokeContext will retrieve the satus from api.test
 func (api *Client) SendAuthRevokeContext(ctx context.Context, token string) (*AuthRevokeResponse, error) {
 	if token == "" {
 		token = api.token
diff --git a/block.go b/block.go
index dbc3449..32ff260 100644
--- a/block.go
+++ b/block.go
@@ -14,7 +14,6 @@ const (
 	MBTImage   MessageBlockType = "image"
 	MBTAction  MessageBlockType = "actions"
 	MBTContext MessageBlockType = "context"
-	MBTFile    MessageBlockType = "file"
 	MBTInput   MessageBlockType = "input"
 )
 
diff --git a/block_conv.go b/block_conv.go
index 43c0c96..ce48ce1 100644
--- a/block_conv.go
+++ b/block_conv.go
@@ -56,16 +56,20 @@ func (b *Blocks) UnmarshalJSON(data []byte) error {
 			block = &ContextBlock{}
 		case "divider":
 			block = &DividerBlock{}
-		case "file":
-			block = &FileBlock{}
 		case "image":
 			block = &ImageBlock{}
 		case "input":
 			block = &InputBlock{}
 		case "section":
 			block = &SectionBlock{}
+		case "rich_text":
+			// for now ignore the (complex) content of rich_text blocks until we can fully support it
+			continue
+		case "file":
+			// for now ignore the file blocks until we can fully support it
+			continue
 		default:
-			block = &UnknownBlock{}
+			return errors.New("unsupported block type")
 		}
 
 		err = json.Unmarshal(r, block)
@@ -249,36 +253,12 @@ func (a *Accessory) UnmarshalJSON(data []byte) error {
 			return err
 		}
 		a.DatePickerElement = element.(*DatePickerBlockElement)
-	case "plain_text_input":
-		element, err := unmarshalBlockElement(r, &PlainTextInputBlockElement{})
-		if err != nil {
-			return err
-		}
-		a.PlainTextInputElement = element.(*PlainTextInputBlockElement)
-	case "radio_buttons":
-		element, err := unmarshalBlockElement(r, &RadioButtonsBlockElement{})
-		if err != nil {
-			return err
-		}
-		a.RadioButtonsElement = element.(*RadioButtonsBlockElement)
-	case "static_select", "external_select", "users_select", "conversations_select", "channels_select":
+	case "static_select":
 		element, err := unmarshalBlockElement(r, &SelectBlockElement{})
 		if err != nil {
 			return err
 		}
 		a.SelectElement = element.(*SelectBlockElement)
-	case "multi_static_select", "multi_external_select", "multi_users_select", "multi_conversations_select", "multi_channels_select":
-		element, err := unmarshalBlockElement(r, &MultiSelectBlockElement{})
-		if err != nil {
-			return err
-		}
-		a.MultiSelectElement = element.(*MultiSelectBlockElement)
-	default:
-		element, err := unmarshalBlockElement(r, &UnknownBlockElement{})
-		if err != nil {
-			return err
-		}
-		a.UnknownElement = element.(*UnknownBlockElement)
 	}
 
 	return nil
@@ -305,18 +285,9 @@ func toBlockElement(element *Accessory) BlockElement {
 	if element.DatePickerElement != nil {
 		return element.DatePickerElement
 	}
-	if element.PlainTextInputElement != nil {
-		return element.PlainTextInputElement
-	}
-	if element.RadioButtonsElement != nil {
-		return element.RadioButtonsElement
-	}
 	if element.SelectElement != nil {
 		return element.SelectElement
 	}
-	if element.MultiSelectElement != nil {
-		return element.MultiSelectElement
-	}
 
 	return nil
 }
diff --git a/block_element.go b/block_element.go
index 8460e95..e0a7bf9 100644
--- a/block_element.go
+++ b/block_element.go
@@ -8,7 +8,6 @@ const (
 	METOverflow       MessageElementType = "overflow"
 	METDatepicker     MessageElementType = "datepicker"
 	METPlainTextInput MessageElementType = "plain_text_input"
-	METRadioButtons   MessageElementType = "radio_buttons"
 
 	MixedElementImage MixedElementType = "mixed_image"
 	MixedElementText  MixedElementType = "mixed_text"
@@ -18,12 +17,6 @@ const (
 	OptTypeUser          string = "users_select"
 	OptTypeConversations string = "conversations_select"
 	OptTypeChannels      string = "channels_select"
-
-	MultiOptTypeStatic        string = "multi_static_select"
-	MultiOptTypeExternal      string = "multi_external_select"
-	MultiOptTypeUser          string = "multi_users_select"
-	MultiOptTypeConversations string = "multi_conversations_select"
-	MultiOptTypeChannels      string = "multi_channels_select"
 )
 
 type MessageElementType string
@@ -39,15 +32,11 @@ type MixedElement interface {
 }
 
 type Accessory struct {
-	ImageElement          *ImageBlockElement
-	ButtonElement         *ButtonBlockElement
-	OverflowElement       *OverflowBlockElement
-	DatePickerElement     *DatePickerBlockElement
-	PlainTextInputElement *PlainTextInputBlockElement
-	RadioButtonsElement   *RadioButtonsBlockElement
-	SelectElement         *SelectBlockElement
-	MultiSelectElement    *MultiSelectBlockElement
-	UnknownElement        *UnknownBlockElement
+	ImageElement      *ImageBlockElement
+	ButtonElement     *ButtonBlockElement
+	OverflowElement   *OverflowBlockElement
+	DatePickerElement *DatePickerBlockElement
+	SelectElement     *SelectBlockElement
 }
 
 // NewAccessory returns a new Accessory for a given block element
@@ -61,17 +50,11 @@ func NewAccessory(element BlockElement) *Accessory {
 		return &Accessory{OverflowElement: element.(*OverflowBlockElement)}
 	case *DatePickerBlockElement:
 		return &Accessory{DatePickerElement: element.(*DatePickerBlockElement)}
-	case *PlainTextInputBlockElement:
-		return &Accessory{PlainTextInputElement: element.(*PlainTextInputBlockElement)}
-	case *RadioButtonsBlockElement:
-		return &Accessory{RadioButtonsElement: element.(*RadioButtonsBlockElement)}
 	case *SelectBlockElement:
 		return &Accessory{SelectElement: element.(*SelectBlockElement)}
-	case *MultiSelectBlockElement:
-		return &Accessory{MultiSelectElement: element.(*MultiSelectBlockElement)}
-	default:
-		return &Accessory{UnknownElement: element.(*UnknownBlockElement)}
 	}
+
+	return nil
 }
 
 // BlockElements is a convenience struct defined to allow dynamic unmarshalling of
@@ -80,20 +63,6 @@ type BlockElements struct {
 	ElementSet []BlockElement `json:"elements,omitempty"`
 }
 
-// UnknownBlockElement any block element that this library does not directly support.
-// See the "Rich Elements" section at the following URL:
-// https://api.slack.com/changelog/2019-09-what-they-see-is-what-you-get-and-more-and-less
-// New block element types may be introduced by Slack at any time; this is a catch-all for any such block elements.
-type UnknownBlockElement struct {
-	Type     MessageElementType `json:"type"`
-	Elements BlockElements
-}
-
-// ElementType returns the type of the Element
-func (s UnknownBlockElement) ElementType() MessageElementType {
-	return s.Type
-}
-
 // ImageBlockElement An element to insert an image - this element can be used
 // in section and context blocks only. If you want a block with only an image
 // in it, you're looking for the image block.
@@ -166,20 +135,6 @@ func NewButtonBlockElement(actionID, value string, text *TextBlockObject) *Butto
 	}
 }
 
-// OptionsResponse defines the response used for select block typahead.
-//
-// More Information: https://api.slack.com/reference/block-kit/block-elements#external_multi_select
-type OptionsResponse struct {
-	Options []*OptionBlockObject `json:"options,omitempty"`
-}
-
-// OptionGroupsResponse defines the response used for select block typahead.
-//
-// More Information: https://api.slack.com/reference/block-kit/block-elements#external_multi_select
-type OptionGroupsResponse struct {
-	OptionGroups []*OptionGroupBlockObject `json:"option_groups,omitempty"`
-}
-
 // SelectBlockElement defines the simplest form of select menu, with a static list
 // of options passed in when defining the element.
 //
@@ -194,7 +149,7 @@ type SelectBlockElement struct {
 	InitialUser         string                    `json:"initial_user,omitempty"`
 	InitialConversation string                    `json:"initial_conversation,omitempty"`
 	InitialChannel      string                    `json:"initial_channel,omitempty"`
-	MinQueryLength      *int                      `json:"min_query_length,omitempty"`
+	MinQueryLength      int                       `json:"min_query_length,omitempty"`
 	Confirm             *ConfirmationBlockObject  `json:"confirm,omitempty"`
 }
 
@@ -230,56 +185,6 @@ func NewOptionsGroupSelectBlockElement(
 	}
 }
 
-// MultiSelectBlockElement defines a multiselect menu, with a static list
-// of options passed in when defining the element.
-//
-// More Information: https://api.slack.com/reference/messaging/block-elements#multi_select
-type MultiSelectBlockElement struct {
-	Type                 string                    `json:"type,omitempty"`
-	Placeholder          *TextBlockObject          `json:"placeholder,omitempty"`
-	ActionID             string                    `json:"action_id,omitempty"`
-	Options              []*OptionBlockObject      `json:"options,omitempty"`
-	OptionGroups         []*OptionGroupBlockObject `json:"option_groups,omitempty"`
-	InitialOptions       []*OptionBlockObject      `json:"initial_options,omitempty"`
-	InitialUsers         []string                  `json:"initial_users,omitempty"`
-	InitialConversations []string                  `json:"initial_conversations,omitempty"`
-	InitialChannels      []string                  `json:"initial_channels,omitempty"`
-	MinQueryLength       *int                      `json:"min_query_length,omitempty"`
-	Confirm              *ConfirmationBlockObject  `json:"confirm,omitempty"`
-}
-
-// ElementType returns the type of the Element
-func (s MultiSelectBlockElement) ElementType() MessageElementType {
-	return MessageElementType(s.Type)
-}
-
-// NewOptionsMultiSelectBlockElement returns a new instance of SelectBlockElement for use with
-// the Options object only.
-func NewOptionsMultiSelectBlockElement(optType string, placeholder *TextBlockObject, actionID string, options ...*OptionBlockObject) *MultiSelectBlockElement {
-	return &MultiSelectBlockElement{
-		Type:        optType,
-		Placeholder: placeholder,
-		ActionID:    actionID,
-		Options:     options,
-	}
-}
-
-// NewOptionsGroupMultiSelectBlockElement returns a new instance of MultiSelectBlockElement for use with
-// the Options object only.
-func NewOptionsGroupMultiSelectBlockElement(
-	optType string,
-	placeholder *TextBlockObject,
-	actionID string,
-	optGroups ...*OptionGroupBlockObject,
-) *MultiSelectBlockElement {
-	return &MultiSelectBlockElement{
-		Type:         optType,
-		Placeholder:  placeholder,
-		ActionID:     actionID,
-		OptionGroups: optGroups,
-	}
-}
-
 // OverflowBlockElement defines the fields needed to use an overflow element.
 // And Overflow Element is like a cross between a button and a select menu -
 // when a user clicks on this overflow button, they will be presented with a
@@ -333,11 +238,10 @@ func NewDatePickerBlockElement(actionID string) *DatePickerBlockElement {
 	}
 }
 
-// PlainTextInputBlockElement creates a field where a user can enter freeform
-// data.
+// PlainTextInputBlockElement creates a field where a user can enter freeform data.
 // Plain-text input elements are currently only available in modals.
 //
-// More Information: https://api.slack.com/reference/block-kit/block-elements#input
+// More Information: https://api.slack.com/reference/messaging/block-elements#input
 type PlainTextInputBlockElement struct {
 	Type         MessageElementType `json:"type"`
 	ActionID     string             `json:"action_id"`
@@ -353,8 +257,7 @@ func (s PlainTextInputBlockElement) ElementType() MessageElementType {
 	return s.Type
 }
 
-// NewPlainTextInputBlockElement returns an instance of a plain-text input
-// element
+// NewPlainTextInputBlockElement returns an instance of a plain-text input element
 func NewPlainTextInputBlockElement(placeholder *TextBlockObject, actionID string) *PlainTextInputBlockElement {
 	return &PlainTextInputBlockElement{
 		Type:        METPlainTextInput,
@@ -362,29 +265,3 @@ func NewPlainTextInputBlockElement(placeholder *TextBlockObject, actionID string
 		Placeholder: placeholder,
 	}
 }
-
-// RadioButtonsBlockElement defines an element which lets users choose one item
-// from a list of possible options.
-//
-// More Information: https://api.slack.com/reference/block-kit/block-elements#radio
-type RadioButtonsBlockElement struct {
-	Type          MessageElementType       `json:"type"`
-	ActionID      string                   `json:"action_id"`
-	Options       []*OptionBlockObject     `json:"options"`
-	InitialOption *OptionBlockObject       `json:"initial_option,omitempty"`
-	Confirm       *ConfirmationBlockObject `json:"confirm,omitempty"`
-}
-
-// ElementType returns the type of the Element
-func (s RadioButtonsBlockElement) ElementType() MessageElementType {
-	return s.Type
-}
-
-// NewRadioButtonsBlockElement returns an instance of a radio buttons element.
-func NewRadioButtonsBlockElement(actionID string, options ...*OptionBlockObject) *RadioButtonsBlockElement {
-	return &RadioButtonsBlockElement{
-		Type:     METRadioButtons,
-		ActionID: actionID,
-		Options:  options,
-	}
-}
diff --git a/block_file.go b/block_file.go
deleted file mode 100644
index ac4453f..0000000
--- a/block_file.go
+++ /dev/null
@@ -1,26 +0,0 @@
-package slack
-
-// FileBlock defines data that is used to display a remote file.
-//
-// More Information: https://api.slack.com/reference/block-kit/blocks#file
-type FileBlock struct {
-	Type       MessageBlockType `json:"type"`
-	BlockID    string           `json:"block_id,omitempty"`
-	ExternalID string           `json:"external_id"`
-	Source     string           `json:"source"`
-}
-
-// BlockType returns the type of the block
-func (s FileBlock) BlockType() MessageBlockType {
-	return s.Type
-}
-
-// NewFileBlock returns a new instance of a file block
-func NewFileBlock(blockID string, externalID string, source string) *FileBlock {
-	return &FileBlock{
-		Type:       MBTFile,
-		BlockID:    blockID,
-		ExternalID: externalID,
-		Source:     source,
-	}
-}
diff --git a/block_input.go b/block_input.go
index 10638cd..9d08203 100644
--- a/block_input.go
+++ b/block_input.go
@@ -1,8 +1,10 @@
 package slack
 
-// InputBlock defines data that is used to display user input fields.
+// InputBlock defines data that is used to collect information from users -
+// it can hold a plain-text input element, a select menu element,
+// a multi-select menu element, or a datepicker.
 //
-// More Information: https://api.slack.com/reference/block-kit/blocks#input
+// More Information: https://api.slack.com/reference/messaging/blocks#input
 type InputBlock struct {
 	Type     MessageBlockType `json:"type"`
 	BlockID  string           `json:"block_id,omitempty"`
@@ -17,7 +19,7 @@ func (s InputBlock) BlockType() MessageBlockType {
 	return s.Type
 }
 
-// NewInputBlock returns a new instance of an input block
+// NewInputBlock returns a new instance of an Input Block
 func NewInputBlock(blockID string, label *TextBlockObject, element BlockElement) *InputBlock {
 	return &InputBlock{
 		Type:    MBTInput,
diff --git a/block_object.go b/block_object.go
index cf3536d..824ec93 100644
--- a/block_object.go
+++ b/block_object.go
@@ -145,14 +145,6 @@ func NewTextBlockObject(elementType, text string, emoji, verbatim bool) *TextBlo
 	}
 }
 
-// BlockType returns the type of the block
-func (t TextBlockObject) BlockType() MessageBlockType {
-	if t.Type == "mrkdown" {
-		return MarkdownType
-	}
-	return PlainTextType
-}
-
 // ConfirmationBlockObject defines a dialog that provides a confirmation step to
 // any interactive element. This dialog will ask the user to confirm their action by
 // offering a confirm and deny buttons.
diff --git a/block_unknown.go b/block_unknown.go
deleted file mode 100644
index 97054c7..0000000
--- a/block_unknown.go
+++ /dev/null
@@ -1,13 +0,0 @@
-package slack
-
-// UnknownBlock represents a block type that is not yet known. This block type exists to prevent Slack from introducing
-// new and unknown block types that break this library.
-type UnknownBlock struct {
-	Type    MessageBlockType `json:"type"`
-	BlockID string           `json:"block_id,omitempty"`
-}
-
-// BlockType returns the type of the block
-func (b UnknownBlock) BlockType() MessageBlockType {
-	return b.Type
-}
diff --git a/channels.go b/channels.go
index a90d238..c99e665 100644
--- a/channels.go
+++ b/channels.go
@@ -4,7 +4,6 @@ import (
 	"context"
 	"net/url"
 	"strconv"
-	"time"
 )
 
 type channelResponseFull struct {
@@ -15,7 +14,6 @@ type channelResponseFull struct {
 	NotInChannel bool      `json:"not_in_channel"`
 	History
 	SlackResponse
-	Metadata ResponseMetadata `json:"response_metadata"`
 }
 
 // Channel contains information about the channel
@@ -37,21 +35,25 @@ func (api *Client) channelRequest(ctx context.Context, path string, values url.V
 	return response, response.Err()
 }
 
+type channelsConfig struct {
+	values url.Values
+}
+
 // GetChannelsOption option provided when getting channels.
-type GetChannelsOption func(*ChannelPagination) error
+type GetChannelsOption func(*channelsConfig) error
 
 // GetChannelsOptionExcludeMembers excludes the members collection from each channel.
 func GetChannelsOptionExcludeMembers() GetChannelsOption {
-	return func(p *ChannelPagination) error {
-		p.excludeMembers = true
+	return func(config *channelsConfig) error {
+		config.values.Add("exclude_members", "true")
 		return nil
 	}
 }
 
 // GetChannelsOptionExcludeArchived excludes archived channels from results.
 func GetChannelsOptionExcludeArchived() GetChannelsOption {
-	return func(p *ChannelPagination) error {
-		p.excludeArchived = true
+	return func(config *channelsConfig) error {
+		config.values.Add("exclude_archived", "true")
 		return nil
 	}
 }
@@ -264,78 +266,6 @@ func (api *Client) KickUserFromChannelContext(ctx context.Context, channelID, us
 	return err
 }
 
-func newChannelPagination(c *Client, options ...GetChannelsOption) (cp ChannelPagination) {
-	cp = ChannelPagination{
-		c:     c,
-		limit: 200, // per slack api documentation.
-	}
-
-	for _, opt := range options {
-		opt(&cp)
-	}
-
-	return cp
-}
-
-// ChannelPagination allows for paginating over the channels
-type ChannelPagination struct {
-	Channels        []Channel
-	limit           int
-	excludeArchived bool
-	excludeMembers  bool
-	previousResp    *ResponseMetadata
-	c               *Client
-}
-
-// Done checks if the pagination has completed
-func (ChannelPagination) Done(err error) bool {
-	return err == errPaginationComplete
-}
-
-// Failure checks if pagination failed.
-func (t ChannelPagination) Failure(err error) error {
-	if t.Done(err) {
-		return nil
-	}
-
-	return err
-}
-
-func (t ChannelPagination) Next(ctx context.Context) (_ ChannelPagination, err error) {
-	var (
-		resp *channelResponseFull
-	)
-
-	if t.c == nil || (t.previousResp != nil && t.previousResp.Cursor == "") {
-		return t, errPaginationComplete
-	}
-
-	t.previousResp = t.previousResp.initialize()
-
-	values := url.Values{
-		"limit":            {strconv.Itoa(t.limit)},
-		"exclude_archived": {strconv.FormatBool(t.excludeArchived)},
-		"exclude_members":  {strconv.FormatBool(t.excludeMembers)},
-		"token":            {t.c.token},
-		"cursor":           {t.previousResp.Cursor},
-	}
-
-	if resp, err = t.c.channelRequest(ctx, "channels.list", values); err != nil {
-		return t, err
-	}
-
-	t.c.Debugf("GetChannelsContext: got %d channels; metadata %v", len(resp.Channels), resp.Metadata)
-	t.Channels = resp.Channels
-	t.previousResp = &resp.Metadata
-
-	return t, nil
-}
-
-// GetChannelsPaginated fetches channels in a paginated fashion, see GetChannelsContext for usage.
-func (api *Client) GetChannelsPaginated(options ...GetChannelsOption) ChannelPagination {
-	return newChannelPagination(api, options...)
-}
-
 // GetChannels retrieves all the channels
 // see https://api.slack.com/methods/channels.list
 func (api *Client) GetChannels(excludeArchived bool, options ...GetChannelsOption) ([]Channel, error) {
@@ -344,27 +274,28 @@ func (api *Client) GetChannels(excludeArchived bool, options ...GetChannelsOptio
 
 // GetChannelsContext retrieves all the channels with a custom context
 // see https://api.slack.com/methods/channels.list
-func (api *Client) GetChannelsContext(ctx context.Context, excludeArchived bool, options ...GetChannelsOption) (results []Channel, err error) {
+func (api *Client) GetChannelsContext(ctx context.Context, excludeArchived bool, options ...GetChannelsOption) ([]Channel, error) {
+	config := channelsConfig{
+		values: url.Values{
+			"token": {api.token},
+		},
+	}
+
 	if excludeArchived {
 		options = append(options, GetChannelsOptionExcludeArchived())
 	}
 
-	p := api.GetChannelsPaginated(options...)
-	for err == nil {
-		p, err = p.Next(ctx)
-		if err == nil {
-			results = append(results, p.Channels...)
-		} else if rateLimitedError, ok := err.(*RateLimitedError); ok {
-			select {
-			case <-ctx.Done():
-				err = ctx.Err()
-			case <-time.After(rateLimitedError.RetryAfter):
-				err = nil
-			}
+	for _, opt := range options {
+		if err := opt(&config); err != nil {
+			return nil, err
 		}
 	}
 
-	return results, p.Failure(err)
+	response, err := api.channelRequest(ctx, "channels.list", config.values)
+	if err != nil {
+		return nil, err
+	}
+	return response.Channels, nil
 }
 
 // SetChannelReadMark sets the read mark of a given channel to a specific point
diff --git a/chat.go b/chat.go
index 1281b15..b54f8d6 100644
--- a/chat.go
+++ b/chat.go
@@ -5,7 +5,6 @@ import (
 	"encoding/json"
 	"net/http"
 	"net/url"
-	"strconv"
 
 	"github.com/slack-go/slack/slackutilsx"
 )
@@ -26,11 +25,10 @@ const (
 )
 
 type chatResponseFull struct {
-	Channel            string `json:"channel"`
-	Timestamp          string `json:"ts"`                             //Regular message timestamp
-	MessageTimeStamp   string `json:"message_ts"`                     //Ephemeral message timestamp
-	ScheduledMessageID string `json:"scheduled_message_id,omitempty"` //Scheduled message id
-	Text               string `json:"text"`
+	Channel          string `json:"channel"`
+	Timestamp        string `json:"ts"`         //Regular message timestamp
+	MessageTimeStamp string `json:"message_ts"` //Ephemeral message timestamp
+	Text             string `json:"text"`
 	SlackResponse
 }
 
@@ -84,34 +82,13 @@ func NewPostMessageParameters() PostMessageParameters {
 
 // DeleteMessage deletes a message in a channel
 func (api *Client) DeleteMessage(channel, messageTimestamp string) (string, string, error) {
-	respChannel, respTimestamp, _, err := api.SendMessageContext(
-		context.Background(),
-		channel,
-		MsgOptionDelete(messageTimestamp),
-	)
+	respChannel, respTimestamp, _, err := api.SendMessageContext(context.Background(), channel, MsgOptionDelete(messageTimestamp))
 	return respChannel, respTimestamp, err
 }
 
 // DeleteMessageContext deletes a message in a channel with a custom context
 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
-}
-
-// ScheduleMessage sends a message to a channel.
-// Message is escaped by default according to https://api.slack.com/docs/formatting
-// Use http://davestevens.github.io/slack-message-builder/ to help crafting your message.
-func (api *Client) ScheduleMessage(channelID, postAt string, options ...MsgOption) (string, string, error) {
-	respChannel, respTimestamp, _, err := api.SendMessageContext(
-		context.Background(),
-		channelID,
-		MsgOptionSchedule(postAt),
-		MsgOptionCompose(options...),
-	)
+	respChannel, respTimestamp, _, err := api.SendMessageContext(ctx, channel, MsgOptionDelete(messageTimestamp))
 	return respChannel, respTimestamp, err
 }
 
@@ -155,33 +132,18 @@ func (api *Client) PostEphemeral(channelID, userID string, options ...MsgOption)
 // PostEphemeralContext sends an ephemeal message to a user in a channel with a custom context
 // For more details, see PostEphemeral documentation
 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...),
-	)
+	_, timestamp, _, err = api.SendMessageContext(ctx, channelID, MsgOptionPostEphemeral(userID), MsgOptionCompose(options...))
 	return timestamp, err
 }
 
 // UpdateMessage updates a message in a channel
 func (api *Client) UpdateMessage(channelID, timestamp string, options ...MsgOption) (string, string, string, error) {
-	return api.SendMessageContext(
-		context.Background(),
-		channelID,
-		MsgOptionUpdate(timestamp),
-		MsgOptionCompose(options...),
-	)
+	return api.SendMessageContext(context.Background(), channelID, MsgOptionUpdate(timestamp), MsgOptionCompose(options...))
 }
 
 // UpdateMessageContext updates a message in a channel
 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...),
-	)
+	return api.SendMessageContext(ctx, channelID, MsgOptionUpdate(timestamp), MsgOptionCompose(options...))
 }
 
 // UnfurlMessage unfurls a message in a channel
@@ -250,14 +212,13 @@ func buildSender(apiurl string, options ...MsgOption) sendConfig {
 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"
+	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 {
@@ -326,15 +287,6 @@ func (t responseURLSender) BuildRequest() (*http.Request, func(*chatResponseFull
 // MsgOption option provided when sending a message.
 type MsgOption func(*sendConfig) error
 
-// MsgOptionSchedule schedules a messages.
-func MsgOptionSchedule(postAt string) MsgOption {
-	return func(config *sendConfig) error {
-		config.endpoint = config.apiurl + string(chatScheduleMessage)
-		config.values.Add("post_at", postAt)
-		return nil
-	}
-}
-
 // MsgOptionPost posts a messages, this is the default.
 func MsgOptionPost() MsgOption {
 	return func(config *sendConfig) error {
@@ -673,81 +625,3 @@ func (api *Client) GetPermalinkContext(ctx context.Context, params *PermalinkPar
 	}
 	return response.Permalink, response.Err()
 }
-
-type GetScheduledMessagesParameters struct {
-	Channel string
-	Cursor  string
-	Latest  string
-	Limit   int
-	Oldest  string
-}
-
-// GetScheduledMessages returns the list of scheduled messages based on params
-func (api *Client) GetScheduledMessages(params *GetScheduledMessagesParameters) (channels []Message, nextCursor string, err error) {
-	return api.GetScheduledMessagesContext(context.Background(), params)
-}
-
-// GetScheduledMessagesContext returns the list of scheduled messages in a Slack team with a custom context
-func (api *Client) GetScheduledMessagesContext(ctx context.Context, params *GetScheduledMessagesParameters) (channels []Message, nextCursor string, err error) {
-	values := url.Values{
-		"token": {api.token},
-	}
-	if params.Channel != "" {
-		values.Add("channel", params.Channel)
-	}
-	if params.Cursor != "" {
-		values.Add("cursor", params.Cursor)
-	}
-	if params.Limit != 0 {
-		values.Add("limit", strconv.Itoa(params.Limit))
-	}
-	if params.Latest != "" {
-		values.Add("latest", params.Latest)
-	}
-	if params.Oldest != "" {
-		values.Add("oldest", params.Oldest)
-	}
-	response := struct {
-		Messages         []Message        `json:"scheduled_messages"`
-		ResponseMetaData responseMetaData `json:"response_metadata"`
-		SlackResponse
-	}{}
-
-	err = api.postMethod(ctx, "chat.scheduledMessages.list", values, &response)
-	if err != nil {
-		return nil, "", err
-	}
-
-	return response.Messages, response.ResponseMetaData.NextCursor, response.Err()
-}
-
-type DeleteScheduledMessageParameters struct {
-	Channel            string
-	ScheduledMessageID string
-	AsUser             bool
-}
-
-// DeleteScheduledMessage returns the list of scheduled messages based on params
-func (api *Client) DeleteScheduledMessage(params *DeleteScheduledMessageParameters) (bool, error) {
-	return api.DeleteScheduledMessageContext(context.Background(), params)
-}
-
-// DeleteScheduledMessageContext returns the list of scheduled messages in a Slack team with a custom context
-func (api *Client) DeleteScheduledMessageContext(ctx context.Context, params *DeleteScheduledMessageParameters) (bool, error) {
-	values := url.Values{
-		"token":                {api.token},
-		"channel":              {params.Channel},
-		"scheduled_message_id": {params.ScheduledMessageID},
-		"as_user":              {strconv.FormatBool(params.AsUser)},
-	}
-	response := struct {
-		SlackResponse
-	}{}
-
-	err := api.postMethod(ctx, "chat.deleteScheduledMessage", values, &response)
-	if err != nil {
-		return false, err
-	}
-
-	return response.Ok, response.Err()
-}
diff --git a/examples/dialog/dialog.go b/examples/dialog/dialog.go
deleted file mode 100644
index e964a86..0000000
--- a/examples/dialog/dialog.go
+++ /dev/null
@@ -1,98 +0,0 @@
-package main
-
-import (
-	"encoding/json"
-	"io/ioutil"
-	"log"
-	"net/http"
-	"net/url"
-	"strings"
-
-	"github.com/slack-go/slack"
-)
-
-var api = slack.New("YOUR_TOKEN")
-var signingSecret = "YOUR_SIGNING_SECRET"
-
-// You can open a dialog with a user interaction. (like pushing buttons, slash commands ...)
-// https://api.slack.com/surfaces/modals
-// https://api.slack.com/interactivity/entry-points
-func main() {
-	http.HandleFunc("/", handler)
-	http.ListenAndServe(":3000", nil)
-}
-
-func handler(w http.ResponseWriter, r *http.Request) {
-
-	// Read request body
-	defer r.Body.Close()
-	body, err := ioutil.ReadAll(r.Body)
-	if err != nil {
-		w.WriteHeader(http.StatusInternalServerError)
-		log.Printf("[ERROR] Fail to read request body: %v", err)
-		return
-	}
-
-	// Verify signing secret
-	sv, err := slack.NewSecretsVerifier(r.Header, signingSecret)
-	if err != nil {
-		w.WriteHeader(http.StatusUnauthorized)
-		log.Printf("[ERROR] Fail to verify SigningSecret: %v", err)
-		return
-	}
-	sv.Write(body)
-	if err := sv.Ensure(); err != nil {
-		w.WriteHeader(http.StatusUnauthorized)
-		log.Printf("[ERROR] Fail to verify SigningSecret: %v", err)
-		return
-	}
-
-	// Parse request body
-	str, _ := url.QueryUnescape(string(body))
-	str = strings.Replace(str, "payload=", "", 1)
-	var message slack.InteractionCallback
-	if err := json.Unmarshal([]byte(str), &message); err != nil {
-		log.Printf("[ERROR] Fail to unmarchal json: %v", err)
-		return
-	}
-
-	switch message.Type {
-	case slack.InteractionTypeInteractionMessage:
-		// Make new dialog components and open a dialog.
-		// Component-Text
-		textInput := slack.NewTextInput("TextSample", "Sample label - Text", "Default value")
-
-		// Component-TextArea
-		textareaInput := slack.NewTextAreaInput("TexaAreaSample", "Sample label - TextArea", "Default value")
-
-		// Component-Select menu
-		option1 := slack.DialogSelectOption{
-			Label: "Display name 1",
-			Value: "Inner value 1",
-		}
-		option2 := slack.DialogSelectOption{
-			Label: "Display name 2",
-			Value: "Inner value 2",
-		}
-		options := []slack.DialogSelectOption{option1, option2}
-		selectInput := slack.NewStaticSelectDialogInput("SelectSample", "Sample label - Select", options)
-
-		// Open a dialog
-		elements := []slack.DialogElement{
-			textInput,
-			textareaInput,
-			selectInput,
-		}
-		dialog := slack.Dialog{
-			CallbackID:  "Callback_ID",
-			Title:       "Dialog title",
-			SubmitLabel: "Submit",
-			Elements:    elements,
-		}
-		api.OpenDialog(message.TriggerID, dialog)
-
-	case slack.InteractionTypeDialogSubmission:
-		// Receive a notification of a dialog submission
-		log.Printf("Successfully receive a dialog submission.")
-	}
-}
diff --git a/examples/websocket_respond/respond.go b/examples/websocket_respond/respond.go
deleted file mode 100644
index eed3fa8..0000000
--- a/examples/websocket_respond/respond.go
+++ /dev/null
@@ -1,50 +0,0 @@
-package main
-
-import (
-	"fmt"
-	"strings"
-
-	"github.com/slack-go/slack"
-)
-
-func main() {
-	api := slack.New(
-		"YOUR-TOKEN-HERE",
-	)
-
-	rtm := api.NewRTM()
-	go rtm.ManageConnection()
-
-	for msg := range rtm.IncomingEvents {
-		switch ev := msg.Data.(type) {
-		case *slack.MessageEvent:
-			msg := ev.Msg
-
-			if msg.SubType != "" {
-				break // We're only handling normal messages.
-			}
-
-			// Create a response object.
-			resp := rtm.NewOutgoingMessage(fmt.Sprintf("echo %s", msg.Text), msg.Channel)
-
-			// Respond in thread if not a direct message.
-			if !strings.HasPrefix(msg.Channel, "D") {
-				resp.ThreadTimestamp = msg.Timestamp
-			}
-
-			// Respond in same thread if message came from a thread.
-			if msg.ThreadTimestamp != "" {
-				resp.ThreadTimestamp = msg.ThreadTimestamp
-			}
-
-			rtm.SendMessage(resp)
-
-		case *slack.ConnectedEvent:
-			fmt.Println("Connected to Slack")
-
-		case *slack.InvalidAuthEvent:
-			fmt.Println("Invalid token")
-			return
-		}
-	}
-}
diff --git a/go.mod b/go.mod
index b57c9b3..cbe1180 100644
--- a/go.mod
+++ b/go.mod
@@ -1,11 +1,12 @@
 module github.com/slack-go/slack
 
+go 1.13
+
 require (
+	github.com/davecgh/go-spew v1.1.1 // indirect
 	github.com/go-test/deep v1.0.4
 	github.com/gorilla/websocket v1.2.0
-	github.com/nlopes/slack v0.6.0
 	github.com/pkg/errors v0.8.0
+	github.com/pmezard/go-difflib v1.0.0 // indirect
 	github.com/stretchr/testify v1.2.2
 )
-
-go 1.13
diff --git a/go.sum b/go.sum
index 196525e..7a0ae46 100644
--- a/go.sum
+++ b/go.sum
@@ -4,8 +4,6 @@ github.com/go-test/deep v1.0.4 h1:u2CU3YKy9I2pmu9pX0eq50wCgjfGIt539SqR7FbHiho=
 github.com/go-test/deep v1.0.4/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA=
 github.com/gorilla/websocket v1.2.0 h1:VJtLvh6VQym50czpZzx07z/kw9EgAxI3x1ZB8taTMQQ=
 github.com/gorilla/websocket v1.2.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
-github.com/nlopes/slack v0.6.0 h1:jt0jxVQGhssx1Ib7naAOZEZcGdtIhTzkP0nopK0AsRA=
-github.com/nlopes/slack v0.6.0/go.mod h1:JzQ9m3PMAqcpeCam7UaHSuBuupz7CmpjehYMayT6YOk=
 github.com/pkg/errors v0.8.0 h1:WdK/asTD0HN+q6hsWO3/vpuAkAr+tw6aNJNDFFf0+qw=
 github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
 github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
diff --git a/history.go b/history.go
index 49dfe35..87b2e1e 100644
--- a/history.go
+++ b/history.go
@@ -22,7 +22,6 @@ type History struct {
 	Latest   string    `json:"latest"`
 	Messages []Message `json:"messages"`
 	HasMore  bool      `json:"has_more"`
-	Unread   int       `json:"unread_count_display"`
 }
 
 // NewHistoryParameters provides an instance of HistoryParameters with all the sane default values set
diff --git a/info.go b/info.go
index ec70624..31f459f 100644
--- a/info.go
+++ b/info.go
@@ -2,381 +2,108 @@ package slack
 
 import (
 	"bytes"
-	"context"
 	"fmt"
-	"net/url"
 	"strconv"
-	"strings"
 	"time"
 )
 
-type UserPrefsCarrier struct {
-	SlackResponse
-	UserPrefs *UserPrefs `json:"prefs"`
-}
-
-// UserPrefs carries a bunch of user settings including some unknown types
+// UserPrefs needs to be implemented
 type UserPrefs struct {
-	UserColors       string `json:"user_colors,omitempty"`
-	ColorNamesInList bool   `json:"color_names_in_list,omitempty"`
-	// Keyboard UnknownType `json:"keyboard"`
-	EmailAlerts                         string `json:"email_alerts,omitempty"`
-	EmailAlertsSleepUntil               int    `json:"email_alerts_sleep_until,omitempty"`
-	EmailTips                           bool   `json:"email_tips,omitempty"`
-	EmailWeekly                         bool   `json:"email_weekly,omitempty"`
-	EmailOffers                         bool   `json:"email_offers,omitempty"`
-	EmailResearch                       bool   `json:"email_research,omitempty"`
-	EmailDeveloper                      bool   `json:"email_developer,omitempty"`
-	WelcomeMessageHidden                bool   `json:"welcome_message_hidden,omitempty"`
-	SearchSort                          string `json:"search_sort,omitempty"`
-	SearchFileSort                      string `json:"search_file_sort,omitempty"`
-	SearchChannelSort                   string `json:"search_channel_sort,omitempty"`
-	SearchPeopleSort                    string `json:"search_people_sort,omitempty"`
-	ExpandInlineImages                  bool   `json:"expand_inline_images,omitempty"`
-	ExpandInternalInlineImages          bool   `json:"expand_internal_inline_images,omitempty"`
-	ExpandSnippets                      bool   `json:"expand_snippets,omitempty"`
-	PostsFormattingGuide                bool   `json:"posts_formatting_guide,omitempty"`
-	SeenWelcome2                        bool   `json:"seen_welcome_2,omitempty"`
-	SeenSSBPrompt                       bool   `json:"seen_ssb_prompt,omitempty"`
-	SpacesNewXpBannerDismissed          bool   `json:"spaces_new_xp_banner_dismissed,omitempty"`
-	SearchOnlyMyChannels                bool   `json:"search_only_my_channels,omitempty"`
-	SearchOnlyCurrentTeam               bool   `json:"search_only_current_team,omitempty"`
-	SearchHideMyChannels                bool   `json:"search_hide_my_channels,omitempty"`
-	SearchOnlyShowOnline                bool   `json:"search_only_show_online,omitempty"`
-	SearchHideDeactivatedUsers          bool   `json:"search_hide_deactivated_users,omitempty"`
-	EmojiMode                           string `json:"emoji_mode,omitempty"`
-	EmojiUse                            string `json:"emoji_use,omitempty"`
-	HasInvited                          bool   `json:"has_invited,omitempty"`
-	HasUploaded                         bool   `json:"has_uploaded,omitempty"`
-	HasCreatedChannel                   bool   `json:"has_created_channel,omitempty"`
-	HasSearched                         bool   `json:"has_searched,omitempty"`
-	SearchExcludeChannels               string `json:"search_exclude_channels,omitempty"`
-	MessagesTheme                       string `json:"messages_theme,omitempty"`
-	WebappSpellcheck                    bool   `json:"webapp_spellcheck,omitempty"`
-	NoJoinedOverlays                    bool   `json:"no_joined_overlays,omitempty"`
-	NoCreatedOverlays                   bool   `json:"no_created_overlays,omitempty"`
-	DropboxEnabled                      bool   `json:"dropbox_enabled,omitempty"`
-	SeenDomainInviteReminder            bool   `json:"seen_domain_invite_reminder,omitempty"`
-	SeenMemberInviteReminder            bool   `json:"seen_member_invite_reminder,omitempty"`
-	MuteSounds                          bool   `json:"mute_sounds,omitempty"`
-	ArrowHistory                        bool   `json:"arrow_history,omitempty"`
-	TabUIReturnSelects                  bool   `json:"tab_ui_return_selects,omitempty"`
-	ObeyInlineImgLimit                  bool   `json:"obey_inline_img_limit,omitempty"`
-	RequireAt                           bool   `json:"require_at,omitempty"`
-	SsbSpaceWindow                      string `json:"ssb_space_window,omitempty"`
-	MacSsbBounce                        string `json:"mac_ssb_bounce,omitempty"`
-	MacSsbBullet                        bool   `json:"mac_ssb_bullet,omitempty"`
-	ExpandNonMediaAttachments           bool   `json:"expand_non_media_attachments,omitempty"`
-	ShowTyping                          bool   `json:"show_typing,omitempty"`
-	PagekeysHandled                     bool   `json:"pagekeys_handled,omitempty"`
-	LastSnippetType                     string `json:"last_snippet_type,omitempty"`
-	DisplayRealNamesOverride            int    `json:"display_real_names_override,omitempty"`
-	DisplayDisplayNames                 bool   `json:"display_display_names,omitempty"`
-	Time24                              bool   `json:"time24,omitempty"`
-	EnterIsSpecialInTbt                 bool   `json:"enter_is_special_in_tbt,omitempty"`
-	MsgInputSendBtn                     bool   `json:"msg_input_send_btn,omitempty"`
-	MsgInputSendBtnAutoSet              bool   `json:"msg_input_send_btn_auto_set,omitempty"`
-	MsgInputStickyComposer              bool   `json:"msg_input_sticky_composer,omitempty"`
-	GraphicEmoticons                    bool   `json:"graphic_emoticons,omitempty"`
-	ConvertEmoticons                    bool   `json:"convert_emoticons,omitempty"`
-	SsEmojis                            bool   `json:"ss_emojis,omitempty"`
-	SeenOnboardingStart                 bool   `json:"seen_onboarding_start,omitempty"`
-	OnboardingCancelled                 bool   `json:"onboarding_cancelled,omitempty"`
-	SeenOnboardingSlackbotConversation  bool   `json:"seen_onboarding_slackbot_conversation,omitempty"`
-	SeenOnboardingChannels              bool   `json:"seen_onboarding_channels,omitempty"`
-	SeenOnboardingDirectMessages        bool   `json:"seen_onboarding_direct_messages,omitempty"`
-	SeenOnboardingInvites               bool   `json:"seen_onboarding_invites,omitempty"`
-	SeenOnboardingSearch                bool   `json:"seen_onboarding_search,omitempty"`
-	SeenOnboardingRecentMentions        bool   `json:"seen_onboarding_recent_mentions,omitempty"`
-	SeenOnboardingStarredItems          bool   `json:"seen_onboarding_starred_items,omitempty"`
-	SeenOnboardingPrivateGroups         bool   `json:"seen_onboarding_private_groups,omitempty"`
-	SeenOnboardingBanner                bool   `json:"seen_onboarding_banner,omitempty"`
-	OnboardingSlackbotConversationStep  int    `json:"onboarding_slackbot_conversation_step,omitempty"`
-	SetTzAutomatically                  bool   `json:"set_tz_automatically,omitempty"`
-	SuppressLinkWarning                 bool   `json:"suppress_link_warning,omitempty"`
-	DndEnabled                          bool   `json:"dnd_enabled,omitempty"`
-	DndStartHour                        string `json:"dnd_start_hour,omitempty"`
-	DndEndHour                          string `json:"dnd_end_hour,omitempty"`
-	DndBeforeMonday                     string `json:"dnd_before_monday,omitempty"`
-	DndAfterMonday                      string `json:"dnd_after_monday,omitempty"`
-	DndEnabledMonday                    string `json:"dnd_enabled_monday,omitempty"`
-	DndBeforeTuesday                    string `json:"dnd_before_tuesday,omitempty"`
-	DndAfterTuesday                     string `json:"dnd_after_tuesday,omitempty"`
-	DndEnabledTuesday                   string `json:"dnd_enabled_tuesday,omitempty"`
-	DndBeforeWednesday                  string `json:"dnd_before_wednesday,omitempty"`
-	DndAfterWednesday                   string `json:"dnd_after_wednesday,omitempty"`
-	DndEnabledWednesday                 string `json:"dnd_enabled_wednesday,omitempty"`
-	DndBeforeThursday                   string `json:"dnd_before_thursday,omitempty"`
-	DndAfterThursday                    string `json:"dnd_after_thursday,omitempty"`
-	DndEnabledThursday                  string `json:"dnd_enabled_thursday,omitempty"`
-	DndBeforeFriday                     string `json:"dnd_before_friday,omitempty"`
-	DndAfterFriday                      string `json:"dnd_after_friday,omitempty"`
-	DndEnabledFriday                    string `json:"dnd_enabled_friday,omitempty"`
-	DndBeforeSaturday                   string `json:"dnd_before_saturday,omitempty"`
-	DndAfterSaturday                    string `json:"dnd_after_saturday,omitempty"`
-	DndEnabledSaturday                  string `json:"dnd_enabled_saturday,omitempty"`
-	DndBeforeSunday                     string `json:"dnd_before_sunday,omitempty"`
-	DndAfterSunday                      string `json:"dnd_after_sunday,omitempty"`
-	DndEnabledSunday                    string `json:"dnd_enabled_sunday,omitempty"`
-	DndDays                             string `json:"dnd_days,omitempty"`
-	DndCustomNewBadgeSeen               bool   `json:"dnd_custom_new_badge_seen,omitempty"`
-	DndNotificationScheduleNewBadgeSeen bool   `json:"dnd_notification_schedule_new_badge_seen,omitempty"`
-	// UnreadCollapsedChannels      unknownType                  `json:"unread_collapsed_channels,omitempty"`
-	SidebarBehavior          string `json:"sidebar_behavior,omitempty"`
-	ChannelSort              string `json:"channel_sort,omitempty"`
-	SeparatePrivateChannels  bool   `json:"separate_private_channels,omitempty"`
-	SeparateSharedChannels   bool   `json:"separate_shared_channels,omitempty"`
-	SidebarTheme             string `json:"sidebar_theme,omitempty"`
-	SidebarThemeCustomValues string `json:"sidebar_theme_custom_values,omitempty"`
-	NoInvitesWidgetInSidebar bool   `json:"no_invites_widget_in_sidebar,omitempty"`
-	NoOmniboxInChannels      bool   `json:"no_omnibox_in_channels,omitempty"`
-
-	KKeyOmniboxAutoHideCount       int    `json:"k_key_omnibox_auto_hide_count,omitempty"`
-	ShowSidebarQuickswitcherButton bool   `json:"show_sidebar_quickswitcher_button,omitempty"`
-	EntOrgWideChannelsSidebar      bool   `json:"ent_org_wide_channels_sidebar,omitempty"`
-	MarkMsgsReadImmediately        bool   `json:"mark_msgs_read_immediately,omitempty"`
-	StartScrollAtOldest            bool   `json:"start_scroll_at_oldest,omitempty"`
-	SnippetEditorWrapLongLines     bool   `json:"snippet_editor_wrap_long_lines,omitempty"`
-	LsDisabled                     bool   `json:"ls_disabled,omitempty"`
-	FKeySearch                     bool   `json:"f_key_search,omitempty"`
-	KKeyOmnibox                    bool   `json:"k_key_omnibox,omitempty"`
-	PromptedForEmailDisabling      bool   `json:"prompted_for_email_disabling,omitempty"`
-	NoMacelectronBanner            bool   `json:"no_macelectron_banner,omitempty"`
-	NoMacssb1Banner                bool   `json:"no_macssb1_banner,omitempty"`
-	NoMacssb2Banner                bool   `json:"no_macssb2_banner,omitempty"`
-	NoWinssb1Banner                bool   `json:"no_winssb1_banner,omitempty"`
-	HideUserGroupInfoPane          bool   `json:"hide_user_group_info_pane,omitempty"`
-	MentionsExcludeAtUserGroups    bool   `json:"mentions_exclude_at_user_groups,omitempty"`
-	MentionsExcludeReactions       bool   `json:"mentions_exclude_reactions,omitempty"`
-	PrivacyPolicySeen              bool   `json:"privacy_policy_seen,omitempty"`
-	EnterpriseMigrationSeen        bool   `json:"enterprise_migration_seen,omitempty"`
-	LastTosAcknowledged            string `json:"last_tos_acknowledged,omitempty"`
-	SearchExcludeBots              bool   `json:"search_exclude_bots,omitempty"`
-	LoadLato2                      bool   `json:"load_lato_2,omitempty"`
-	FullerTimestamps               bool   `json:"fuller_timestamps,omitempty"`
-	LastSeenAtChannelWarning       int    `json:"last_seen_at_channel_warning,omitempty"`
-	EmojiAutocompleteBig           bool   `json:"emoji_autocomplete_big,omitempty"`
-	TwoFactorAuthEnabled           bool   `json:"two_factor_auth_enabled,omitempty"`
-	// TwoFactorType                         unknownType    `json:"two_factor_type,omitempty"`
-	// TwoFactorBackupType                   unknownType    `json:"two_factor_backup_type,omitempty"`
-	HideHexSwatch          bool   `json:"hide_hex_swatch,omitempty"`
-	ShowJumperScores       bool   `json:"show_jumper_scores,omitempty"`
-	EnterpriseMdmCustomMsg string `json:"enterprise_mdm_custom_msg,omitempty"`
-	// EnterpriseExcludedAppTeams                 unknownType    `json:"enterprise_excluded_app_teams,omitempty"`
-	ClientLogsPri             string `json:"client_logs_pri,omitempty"`
-	FlannelServerPool         string `json:"flannel_server_pool,omitempty"`
-	MentionsExcludeAtChannels bool   `json:"mentions_exclude_at_channels,omitempty"`
-	ConfirmClearAllUnreads    bool   `json:"confirm_clear_all_unreads,omitempty"`
-	ConfirmUserMarkedAway     bool   `json:"confirm_user_marked_away,omitempty"`
-	BoxEnabled                bool   `json:"box_enabled,omitempty"`
-	SeenSingleEmojiMsg        bool   `json:"seen_single_emoji_msg,omitempty"`
-	ConfirmShCallStart        bool   `json:"confirm_sh_call_start,omitempty"`
-	PreferredSkinTone         string `json:"preferred_skin_tone,omitempty"`
-	ShowAllSkinTones          bool   `json:"show_all_skin_tones,omitempty"`
-	WhatsNewRead              int    `json:"whats_new_read,omitempty"`
-	// FrecencyJumper                           unknownType      `json:"frecency_jumper,omitempty"`
-	FrecencyEntJumper                       string `json:"frecency_ent_jumper,omitempty"`
-	FrecencyEntJumperBackup                 string `json:"frecency_ent_jumper_backup,omitempty"`
-	Jumbomoji                               bool   `json:"jumbomoji,omitempty"`
-	NewxpSeenLastMessage                    int    `json:"newxp_seen_last_message,omitempty"`
-	ShowMemoryInstrument                    bool   `json:"show_memory_instrument,omitempty"`
-	EnableUnreadView                        bool   `json:"enable_unread_view,omitempty"`
-	SeenUnreadViewCoachmark                 bool   `json:"seen_unread_view_coachmark,omitempty"`
-	EnableReactEmojiPicker                  bool   `json:"enable_react_emoji_picker,omitempty"`
-	SeenCustomStatusBadge                   bool   `json:"seen_custom_status_badge,omitempty"`
-	SeenCustomStatusCallout                 bool   `json:"seen_custom_status_callout,omitempty"`
-	SeenCustomStatusExpirationBadge         bool   `json:"seen_custom_status_expiration_badge,omitempty"`
-	UsedCustomStatusKbShortcut              bool   `json:"used_custom_status_kb_shortcut,omitempty"`
-	SeenGuestAdminSlackbotAnnouncement      bool   `json:"seen_guest_admin_slackbot_announcement,omitempty"`
-	SeenThreadsNotificationBanner           bool   `json:"seen_threads_notification_banner,omitempty"`
-	SeenNameTaggingCoachmark                bool   `json:"seen_name_tagging_coachmark,omitempty"`
-	AllUnreadsSortOrder                     string `json:"all_unreads_sort_order,omitempty"`
-	Locale                                  string `json:"locale,omitempty"`
-	SeenIntlChannelNamesCoachmark           bool   `json:"seen_intl_channel_names_coachmark,omitempty"`
-	SeenP2LocaleChangeMessage               int    `json:"seen_p2_locale_change_message,omitempty"`
-	SeenLocaleChangeMessage                 int    `json:"seen_locale_change_message,omitempty"`
-	SeenJapaneseLocaleChangeMessage         bool   `json:"seen_japanese_locale_change_message,omitempty"`
-	SeenSharedChannelsCoachmark             bool   `json:"seen_shared_channels_coachmark,omitempty"`
-	SeenSharedChannelsOptInChangeMessage    bool   `json:"seen_shared_channels_opt_in_change_message,omitempty"`
-	HasRecentlySharedaChannel               bool   `json:"has_recently_shared_a_channel,omitempty"`
-	SeenChannelBrowserAdminCoachmark        bool   `json:"seen_channel_browser_admin_coachmark,omitempty"`
-	SeenAdministrationMenu                  bool   `json:"seen_administration_menu,omitempty"`
-	SeenDraftsSectionCoachmark              bool   `json:"seen_drafts_section_coachmark,omitempty"`
-	SeenEmojiUpdateOverlayCoachmark         bool   `json:"seen_emoji_update_overlay_coachmark,omitempty"`
-	SeenSonicDeluxeToast                    int    `json:"seen_sonic_deluxe_toast,omitempty"`
-	SeenWysiwygDeluxeToast                  bool   `json:"seen_wysiwyg_deluxe_toast,omitempty"`
-	SeenMarkdownPasteToast                  int    `json:"seen_markdown_paste_toast,omitempty"`
-	SeenMarkdownPasteShortcut               int    `json:"seen_markdown_paste_shortcut,omitempty"`
-	SeenIaEducation                         bool   `json:"seen_ia_education,omitempty"`
-	PlainTextMode                           bool   `json:"plain_text_mode,omitempty"`
-	ShowSharedChannelsEducationBanner       bool   `json:"show_shared_channels_education_banner,omitempty"`
-	AllowCallsToSetCurrentStatus            bool   `json:"allow_calls_to_set_current_status,omitempty"`
-	InInteractiveMasMigrationFlow           bool   `json:"in_interactive_mas_migration_flow,omitempty"`
-	SunsetInteractiveMessageViews           int    `json:"sunset_interactive_message_views,omitempty"`
-	ShdepPromoCodeSubmitted                 bool   `json:"shdep_promo_code_submitted,omitempty"`
-	SeenShdepSlackbotMessage                bool   `json:"seen_shdep_slackbot_message,omitempty"`
-	SeenCallsInteractiveCoachmark           bool   `json:"seen_calls_interactive_coachmark,omitempty"`
-	AllowCmdTabIss                          bool   `json:"allow_cmd_tab_iss,omitempty"`
-	SeenWorkflowBuilderDeluxeToast          bool   `json:"seen_workflow_builder_deluxe_toast,omitempty"`
-	WorkflowBuilderIntroModalClickedThrough bool   `json:"workflow_builder_intro_modal_clicked_through,omitempty"`
-	// WorkflowBuilderCoachmarks                    unknownType  `json:"workflow_builder_coachmarks,omitempty"`
-	SeenGdriveCoachmark                            bool   `json:"seen_gdrive_coachmark,omitempty"`
-	OverloadedMessageEnabled                       bool   `json:"overloaded_message_enabled,omitempty"`
-	SeenHighlightsCoachmark                        bool   `json:"seen_highlights_coachmark,omitempty"`
-	SeenHighlightsArrowsCoachmark                  bool   `json:"seen_highlights_arrows_coachmark,omitempty"`
-	SeenHighlightsWarmWelcome                      bool   `json:"seen_highlights_warm_welcome,omitempty"`
-	SeenNewSearchUi                                bool   `json:"seen_new_search_ui,omitempty"`
-	SeenChannelSearch                              bool   `json:"seen_channel_search,omitempty"`
-	SeenPeopleSearch                               bool   `json:"seen_people_search,omitempty"`
-	SeenPeopleSearchCount                          int    `json:"seen_people_search_count,omitempty"`
-	DismissedScrollSearchTooltipCount              int    `json:"dismissed_scroll_search_tooltip_count,omitempty"`
-	LastDismissedScrollSearchTooltipTimestamp      int    `json:"last_dismissed_scroll_search_tooltip_timestamp,omitempty"`
-	HasUsedQuickswitcherShortcut                   bool   `json:"has_used_quickswitcher_shortcut,omitempty"`
-	SeenQuickswitcherShortcutTipCount              int    `json:"seen_quickswitcher_shortcut_tip_count,omitempty"`
-	BrowsersDismissedChannelsLowResultsEducation   bool   `json:"browsers_dismissed_channels_low_results_education,omitempty"`
-	BrowsersSeenInitialChannelsEducation           bool   `json:"browsers_seen_initial_channels_education,omitempty"`
-	BrowsersDismissedPeopleLowResultsEducation     bool   `json:"browsers_dismissed_people_low_results_education,omitempty"`
-	BrowsersSeenInitialPeopleEducation             bool   `json:"browsers_seen_initial_people_education,omitempty"`
-	BrowsersDismissedUserGroupsLowResultsEducation bool   `json:"browsers_dismissed_user_groups_low_results_education,omitempty"`
-	BrowsersSeenInitialUserGroupsEducation         bool   `json:"browsers_seen_initial_user_groups_education,omitempty"`
-	BrowsersDismissedFilesLowResultsEducation      bool   `json:"browsers_dismissed_files_low_results_education,omitempty"`
-	BrowsersSeenInitialFilesEducation              bool   `json:"browsers_seen_initial_files_education,omitempty"`
-	A11yAnimations                                 bool   `json:"a11y_animations,omitempty"`
-	SeenKeyboardShortcutsCoachmark                 bool   `json:"seen_keyboard_shortcuts_coachmark,omitempty"`
-	NeedsInitialPasswordSet                        bool   `json:"needs_initial_password_set,omitempty"`
-	LessonsEnabled                                 bool   `json:"lessons_enabled,omitempty"`
-	TractorEnabled                                 bool   `json:"tractor_enabled,omitempty"`
-	TractorExperimentGroup                         string `json:"tractor_experiment_group,omitempty"`
-	OpenedSlackbotDm                               bool   `json:"opened_slackbot_dm,omitempty"`
-	NewxpSuggestedChannels                         string `json:"newxp_suggested_channels,omitempty"`
-	OnboardingComplete                             bool   `json:"onboarding_complete,omitempty"`
-	WelcomePlaceState                              string `json:"welcome_place_state,omitempty"`
-	// OnboardingRoleApps  unknownType `json:"onboarding_role_apps,omitempty"`
-	HasReceivedThreadedMessage        bool   `json:"has_received_threaded_message,omitempty"`
-	SendYourFirstMessageBannerEnabled bool   `json:"send_your_first_message_banner_enabled,omitempty"`
-	WhocanseethisDmMpdmBadge          bool   `json:"whocanseethis_dm_mpdm_badge,omitempty"`
-	HighlightWords                    string `json:"highlight_words,omitempty"`
-	ThreadsEverything                 bool   `json:"threads_everything,omitempty"`
-	NoTextInNotifications             bool   `json:"no_text_in_notifications,omitempty"`
-	PushShowPreview                   bool   `json:"push_show_preview,omitempty"`
-	GrowlsEnabled                     bool   `json:"growls_enabled,omitempty"`
-	AllChannelsLoud                   bool   `json:"all_channels_loud,omitempty"`
-	PushDmAlert                       bool   `json:"push_dm_alert,omitempty"`
-	PushMentionAlert                  bool   `json:"push_mention_alert,omitempty"`
-	PushEverything                    bool   `json:"push_everything,omitempty"`
-	PushIdleWait                      int    `json:"push_idle_wait,omitempty"`
-	PushSound                         string `json:"push_sound,omitempty"`
-	NewMsgSnd                         string `json:"new_msg_snd,omitempty"`
-	PushLoudChannels                  string `json:"push_loud_channels,omitempty"`
-	PushMentionChannels               string `json:"push_mention_channels,omitempty"`
-	PushLoudChannelsSet               string `json:"push_loud_channels_set,omitempty"`
-	LoudChannels                      string `json:"loud_channels,omitempty"`
-	NeverChannels                     string `json:"never_channels,omitempty"`
-	LoudChannelsSet                   string `json:"loud_channels_set,omitempty"`
-	AtChannelSuppressedChannels       string `json:"at_channel_suppressed_channels,omitempty"`
-	PushAtChannelSuppressedChannels   string `json:"push_at_channel_suppressed_channels,omitempty"`
-	MutedChannels                     string `json:"muted_channels,omitempty"`
-	// AllNotificationsPrefs                  unknownType `json:"all_notifications_prefs,omitempty"`
-	GrowthMsgLimitApproachingCtaCount     int `json:"growth_msg_limit_approaching_cta_count,omitempty"`
-	GrowthMsgLimitApproachingCtaTs        int `json:"growth_msg_limit_approaching_cta_ts,omitempty"`
-	GrowthMsgLimitReachedCtaCount         int `json:"growth_msg_limit_reached_cta_count,omitempty"`
-	GrowthMsgLimitReachedCtaLastTs        int `json:"growth_msg_limit_reached_cta_last_ts,omitempty"`
-	GrowthMsgLimitLongReachedCtaCount     int `json:"growth_msg_limit_long_reached_cta_count,omitempty"`
-	GrowthMsgLimitLongReachedCtaLastTs    int `json:"growth_msg_limit_long_reached_cta_last_ts,omitempty"`
-	GrowthMsgLimitSixtyDayBannerCtaCount  int `json:"growth_msg_limit_sixty_day_banner_cta_count,omitempty"`
-	GrowthMsgLimitSixtyDayBannerCtaLastTs int `json:"growth_msg_limit_sixty_day_banner_cta_last_ts,omitempty"`
-	// GrowthAllBannersPrefs unknownType `json:"growth_all_banners_prefs,omitempty"`
-	AnalyticsUpsellCoachmarkSeen bool `json:"analytics_upsell_coachmark_seen,omitempty"`
-	SeenAppSpaceCoachmark        bool `json:"seen_app_space_coachmark,omitempty"`
-	SeenAppSpaceTutorial         bool `json:"seen_app_space_tutorial,omitempty"`
-	DismissedAppLauncherWelcome  bool `json:"dismissed_app_launcher_welcome,omitempty"`
-	DismissedAppLauncherLimit    bool `json:"dismissed_app_launcher_limit,omitempty"`
-	Purchaser                    bool `json:"purchaser,omitempty"`
-	ShowEntOnboarding            bool `json:"show_ent_onboarding,omitempty"`
-	FoldersEnabled               bool `json:"folders_enabled,omitempty"`
-	// FolderData unknownType `json:"folder_data,omitempty"`
-	SeenCorporateExportAlert               bool   `json:"seen_corporate_export_alert,omitempty"`
-	ShowAutocompleteHelp                   int    `json:"show_autocomplete_help,omitempty"`
-	DeprecationToastLastSeen               int    `json:"deprecation_toast_last_seen,omitempty"`
-	DeprecationModalLastSeen               int    `json:"deprecation_modal_last_seen,omitempty"`
-	Iap1Lab                                int    `json:"iap1_lab,omitempty"`
-	IaTopNavTheme                          string `json:"ia_top_nav_theme,omitempty"`
-	IaPlatformActionsLab                   int    `json:"ia_platform_actions_lab,omitempty"`
-	ActivityView                           string `json:"activity_view,omitempty"`
-	FailoverProxyCheckCompleted            int    `json:"failover_proxy_check_completed,omitempty"`
-	EdgeUploadProxyCheckCompleted          int    `json:"edge_upload_proxy_check_completed,omitempty"`
-	AppSubdomainCheckCompleted             int    `json:"app_subdomain_check_completed,omitempty"`
-	AddAppsPromptDismissed                 bool   `json:"add_apps_prompt_dismissed,omitempty"`
-	AddChannelPromptDismissed              bool   `json:"add_channel_prompt_dismissed,omitempty"`
-	ChannelSidebarHideInvite               bool   `json:"channel_sidebar_hide_invite,omitempty"`
-	InProdSurveysEnabled                   bool   `json:"in_prod_surveys_enabled,omitempty"`
-	DismissedInstalledAppDmSuggestions     string `json:"dismissed_installed_app_dm_suggestions,omitempty"`
-	SeenContextualMessageShortcutsModal    bool   `json:"seen_contextual_message_shortcuts_modal,omitempty"`
-	SeenMessageNavigationEducationalToast  bool   `json:"seen_message_navigation_educational_toast,omitempty"`
-	ContextualMessageShortcutsModalWasSeen bool   `json:"contextual_message_shortcuts_modal_was_seen,omitempty"`
-	MessageNavigationToastWasSeen          bool   `json:"message_navigation_toast_was_seen,omitempty"`
-	UpToBrowseKbShortcut                   bool   `json:"up_to_browse_kb_shortcut,omitempty"`
-	ChannelSections                        string `json:"channel_sections,omitempty"`
-	TZ                                     string `json:"tz,omitempty"`
-}
-
-func (api *Client) GetUserPrefs() (*UserPrefsCarrier, error) {
-	values := url.Values{"token": {api.token}}
-	response := UserPrefsCarrier{}
-
-	err := api.getMethod(context.Background(), "users.prefs.get", values, &response)
-	if err != nil {
-		return nil, err
-	}
-
-	return &response, response.Err()
-}
-
-func (api *Client) MuteChat(channelID string) (*UserPrefsCarrier, error) {
-	prefs, err := api.GetUserPrefs()
-	if err != nil {
-		return nil, err
-	}
-	chnls := strings.Split(prefs.UserPrefs.MutedChannels, ",")
-	for _, chn := range chnls {
-		if chn == channelID {
-			return nil, nil // noop
-		}
-	}
-	newChnls := prefs.UserPrefs.MutedChannels + "," + channelID
-	values := url.Values{"token": {api.token}, "muted_channels": {newChnls}, "reason": {"update-muted-channels"}}
-	response := UserPrefsCarrier{}
-
-	err = api.postMethod(context.Background(), "users.prefs.set", values, &response)
-	if err != nil {
-		return nil, err
-	}
-
-	return &response, response.Err()
-}
-
-func (api *Client) UnMuteChat(channelID string) (*UserPrefsCarrier, error) {
-	prefs, err := api.GetUserPrefs()
-	if err != nil {
-		return nil, err
-	}
-	chnls := strings.Split(prefs.UserPrefs.MutedChannels, ",")
-	newChnls := make([]string, len(chnls)-1)
-	for i, chn := range chnls {
-		if chn == channelID {
-			return nil, nil // noop
-		}
-		newChnls[i] = chn
-	}
-	values := url.Values{"token": {api.token}, "muted_channels": {strings.Join(newChnls, ",")}, "reason": {"update-muted-channels"}}
-	response := UserPrefsCarrier{}
-
-	err = api.postMethod(context.Background(), "users.prefs.set", values, &response)
-	if err != nil {
-		return nil, err
-	}
-
-	return &response, response.Err()
+	// "highlight_words":"",
+	// "user_colors":"",
+	// "color_names_in_list":true,
+	// "growls_enabled":true,
+	// "tz":"Europe\/London",
+	// "push_dm_alert":true,
+	// "push_mention_alert":true,
+	// "push_everything":true,
+	// "push_idle_wait":2,
+	// "push_sound":"b2.mp3",
+	// "push_loud_channels":"",
+	// "push_mention_channels":"",
+	// "push_loud_channels_set":"",
+	// "email_alerts":"instant",
+	// "email_alerts_sleep_until":0,
+	// "email_misc":false,
+	// "email_weekly":true,
+	// "welcome_message_hidden":false,
+	// "all_channels_loud":true,
+	// "loud_channels":"",
+	// "never_channels":"",
+	// "loud_channels_set":"",
+	// "show_member_presence":true,
+	// "search_sort":"timestamp",
+	// "expand_inline_imgs":true,
+	// "expand_internal_inline_imgs":true,
+	// "expand_snippets":false,
+	// "posts_formatting_guide":true,
+	// "seen_welcome_2":true,
+	// "seen_ssb_prompt":false,
+	// "search_only_my_channels":false,
+	// "emoji_mode":"default",
+	// "has_invited":true,
+	// "has_uploaded":false,
+	// "has_created_channel":true,
+	// "search_exclude_channels":"",
+	// "messages_theme":"default",
+	// "webapp_spellcheck":true,
+	// "no_joined_overlays":false,
+	// "no_created_overlays":true,
+	// "dropbox_enabled":false,
+	// "seen_user_menu_tip_card":true,
+	// "seen_team_menu_tip_card":true,
+	// "seen_channel_menu_tip_card":true,
+	// "seen_message_input_tip_card":true,
+	// "seen_channels_tip_card":true,
+	// "seen_domain_invite_reminder":false,
+	// "seen_member_invite_reminder":false,
+	// "seen_flexpane_tip_card":true,
+	// "seen_search_input_tip_card":true,
+	// "mute_sounds":false,
+	// "arrow_history":false,
+	// "tab_ui_return_selects":true,
+	// "obey_inline_img_limit":true,
+	// "new_msg_snd":"knock_brush.mp3",
+	// "collapsible":false,
+	// "collapsible_by_click":true,
+	// "require_at":false,
+	// "mac_ssb_bounce":"",
+	// "mac_ssb_bullet":true,
+	// "win_ssb_bullet":true,
+	// "expand_non_media_attachments":true,
+	// "show_typing":true,
+	// "pagekeys_handled":true,
+	// "last_snippet_type":"",
+	// "display_real_names_override":0,
+	// "time24":false,
+	// "enter_is_special_in_tbt":false,
+	// "graphic_emoticons":false,
+	// "convert_emoticons":true,
+	// "autoplay_chat_sounds":true,
+	// "ss_emojis":true,
+	// "sidebar_behavior":"",
+	// "mark_msgs_read_immediately":true,
+	// "start_scroll_at_oldest":true,
+	// "snippet_editor_wrap_long_lines":false,
+	// "ls_disabled":false,
+	// "sidebar_theme":"default",
+	// "sidebar_theme_custom_values":"",
+	// "f_key_search":false,
+	// "k_key_omnibox":true,
+	// "speak_growls":false,
+	// "mac_speak_voice":"com.apple.speech.synthesis.voice.Alex",
+	// "mac_speak_speed":250,
+	// "comma_key_prefs":false,
+	// "at_channel_suppressed_channels":"",
+	// "push_at_channel_suppressed_channels":"",
+	// "prompted_for_email_disabling":false,
+	// "full_text_extracts":false,
+	// "no_text_in_notifications":false,
+	// "muted_channels":"",
+	// "no_macssb1_banner":false,
+	// "privacy_policy_seen":true,
+	// "search_exclude_bots":false,
+	// "fuzzy_matching":false
 }
 
 // UserDetails contains user details coming in the initial response from StartRTM
diff --git a/interactions.go b/interactions.go
index c56a34f..26a8b6d 100644
--- a/interactions.go
+++ b/interactions.go
@@ -24,9 +24,6 @@ const (
 	InteractionTypeInteractionMessage = InteractionType("interactive_message")
 	InteractionTypeMessageAction      = InteractionType("message_action")
 	InteractionTypeBlockActions       = InteractionType("block_actions")
-	InteractionTypeBlockSuggestion    = InteractionType("block_suggestion")
-	InteractionTypeViewSubmission     = InteractionType("view_submission")
-	InteractionTypeViewClosed         = InteractionType("view_closed")
 )
 
 // InteractionCallback is sent from slack when a user interactions with a button or dialog.
@@ -47,19 +44,8 @@ type InteractionCallback struct {
 	MessageTs       string          `json:"message_ts"`
 	AttachmentID    string          `json:"attachment_id"`
 	ActionCallback  ActionCallbacks `json:"actions"`
-	View            View            `json:"view"`
-	ActionID        string          `json:"action_id"`
 	APIAppID        string          `json:"api_app_id"`
-	BlockID         string          `json:"block_id"`
-	Container       Container       `json:"container"`
 	DialogSubmissionCallback
-	ViewSubmissionCallback
-	ViewClosedCallback
-}
-
-type Container struct {
-	Type   string `json:"type"`
-	ViewID string `json:"view_id"`
 }
 
 // ActionCallback is a convenience struct defined to allow dynamic unmarshalling of
diff --git a/messages.go b/messages.go
index f2f5b14..24d401a 100644
--- a/messages.go
+++ b/messages.go
@@ -22,7 +22,6 @@ type Message struct {
 // Msg contains information about a slack message
 type Msg struct {
 	// Basic Message
-	ClientMsgID     string       `json:"client_msg_id"`
 	Type            string       `json:"type,omitempty"`
 	Channel         string       `json:"channel,omitempty"`
 	User            string       `json:"user,omitempty"`
diff --git a/oauth.go b/oauth.go
index 64118fb..29d6dce 100644
--- a/oauth.go
+++ b/oauth.go
@@ -31,40 +31,6 @@ type OAuthResponse struct {
 	SlackResponse
 }
 
-// OAuthV2Response ...
-type OAuthV2Response struct {
-	AccessToken string                    `json:"access_token"`
-	TokenType   string                    `json:"token_type"`
-	Scope       string                    `json:"scope"`
-	BotUserID   string                    `json:"bot_user_id"`
-	AppID       string                    `json:"app_id"`
-	TeamID      string                    `json:"team_id"`
-	Team        OAuthV2ResponseTeam       `json:"team"`
-	Enterprise  OAuthV2ResponseEnterprise `json:"enterprise"`
-	AuthedUser  OAuthV2ResponseAuthedUser `json:"authed_user"`
-	SlackResponse
-}
-
-// OAuthV2ResponseTeam ...
-type OAuthV2ResponseTeam struct {
-	ID   string `json:"id"`
-	Name string `json:"name"`
-}
-
-// OAuthV2ResponseEnterprise ...
-type OAuthV2ResponseEnterprise struct {
-	ID   string `json:"id"`
-	Name string `json:"name"`
-}
-
-// OAuthV2ResponseAuthedUser ...
-type OAuthV2ResponseAuthedUser struct {
-	ID          string `json:"id"`
-	Scope       string `json:"scope"`
-	AccessToken string `json:"access_token"`
-	TokenType   string `json:"token_type"`
-}
-
 // GetOAuthToken retrieves an AccessToken
 func GetOAuthToken(client httpClient, clientID, clientSecret, code, redirectURI string) (accessToken string, scope string, err error) {
 	return GetOAuthTokenContext(context.Background(), client, clientID, clientSecret, code, redirectURI)
@@ -96,23 +62,3 @@ func GetOAuthResponseContext(ctx context.Context, client httpClient, clientID, c
 	}
 	return response, response.Err()
 }
-
-// GetOAuthV2Response gets a V2 OAuth access token response - https://api.slack.com/methods/oauth.v2.access
-func GetOAuthV2Response(client httpClient, clientID, clientSecret, code, redirectURI string) (resp *OAuthV2Response, err error) {
-	return GetOAuthV2ResponseContext(context.Background(), client, clientID, clientSecret, code, redirectURI)
-}
-
-// GetOAuthV2ResponseContext with a context, gets a V2 OAuth access token response
-func GetOAuthV2ResponseContext(ctx context.Context, client httpClient, clientID, clientSecret, code, redirectURI string) (resp *OAuthV2Response, err error) {
-	values := url.Values{
-		"client_id":     {clientID},
-		"client_secret": {clientSecret},
-		"code":          {code},
-		"redirect_uri":  {redirectURI},
-	}
-	response := &OAuthV2Response{}
-	if err = postForm(ctx, client, APIURL+"oauth.v2.access", values, response, discard{}); err != nil {
-		return nil, err
-	}
-	return response, response.Err()
-}
diff --git a/slackevents/inner_events.go b/slackevents/inner_events.go
index 84f8208..c4b170a 100644
--- a/slackevents/inner_events.go
+++ b/slackevents/inner_events.go
@@ -23,6 +23,10 @@ type AppMentionEvent struct {
 	ThreadTimeStamp string      `json:"thread_ts"`
 	Channel         string      `json:"channel"`
 	EventTimeStamp  json.Number `json:"event_ts"`
+
+	// When Message comes from a channel that is shared between workspaces
+	UserTeam   string `json:"user_team,omitempty"`
+	SourceTeam string `json:"source_team,omitempty"`
 }
 
 // AppHomeOpenedEvent Your Slack app home was opened.
@@ -85,6 +89,10 @@ type MessageEvent struct {
 	ChannelType     string      `json:"channel_type"`
 	EventTimeStamp  json.Number `json:"event_ts"`
 
+	// When Message comes from a channel that is shared between workspaces
+	UserTeam   string `json:"user_team,omitempty"`
+	SourceTeam string `json:"source_team,omitempty"`
+
 	// Edited Message
 	Message         *MessageEvent `json:"message,omitempty"`
 	PreviousMessage *MessageEvent `json:"previous_message,omitempty"`
@@ -121,21 +129,6 @@ type pinEvent struct {
 	HasPins        bool   `json:"has_pins,omitempty"`
 }
 
-type reactionEvent struct {
-	Type           string `json:"type"`
-	User           string `json:"user"`
-	Reaction       string `json:"reaction"`
-	ItemUser       string `json:"item_user"`
-	Item           Item   `json:"item"`
-	EventTimestamp string `json:"event_ts"`
-}
-
-// ReactionAddedEvent An reaction was added to a message - https://api.slack.com/events/reaction_added
-type ReactionAddedEvent reactionEvent
-
-// ReactionRemovedEvent An reaction was removed from a message - https://api.slack.com/events/reaction_removed
-type ReactionRemovedEvent reactionEvent
-
 // PinAddedEvent An item was pinned to a channel - https://api.slack.com/events/pin_added
 type PinAddedEvent pinEvent
 
@@ -275,10 +268,6 @@ const (
 	PinAdded = "pin_added"
 	// PinRemoved An item was unpinned from a channel
 	PinRemoved = "pin_removed"
-	// ReactionAdded An reaction was added to a message
-	ReactionAdded = "reaction_added"
-	// ReactionRemoved An reaction was removed from a message
-	ReactionRemoved = "reaction_removed"
 	// TokensRevoked APP's API tokes are revoked
 	TokensRevoked = "tokens_revoked"
 )
@@ -297,7 +286,5 @@ var EventsAPIInnerEventMapping = map[string]interface{}{
 	MemberJoinedChannel:   MemberJoinedChannelEvent{},
 	PinAdded:              PinAddedEvent{},
 	PinRemoved:            PinRemovedEvent{},
-	ReactionAdded:         ReactionAddedEvent{},
-	ReactionRemoved:       ReactionRemovedEvent{},
 	TokensRevoked:         TokensRevokedEvent{},
 }
diff --git a/views.go b/views.go
index c34feec..afe391b 100644
--- a/views.go
+++ b/views.go
@@ -12,10 +12,6 @@ const (
 
 type ViewType string
 
-type ViewState struct {
-	Values map[string]map[string]BlockAction `json:"values"`
-}
-
 type View struct {
 	SlackResponse
 	ID              string           `json:"id"`
@@ -27,7 +23,7 @@ type View struct {
 	Blocks          Blocks           `json:"blocks"`
 	PrivateMetadata string           `json:"private_metadata"`
 	CallbackID      string           `json:"callback_id"`
-	State           *ViewState       `json:"state"`
+	State           interface{}      `json:"state"`
 	Hash            string           `json:"hash"`
 	ClearOnClose    bool             `json:"clear_on_close"`
 	NotifyOnClose   bool             `json:"notify_on_close"`
@@ -38,67 +34,17 @@ type View struct {
 	BotID           string           `json:"bot_id"`
 }
 
-type ViewSubmissionCallback struct {
-	Hash string `json:"hash"`
-}
-
-type ViewClosedCallback struct {
-	IsCleared bool `json:"is_cleared"`
-}
-
-const (
-	RAClear  ViewResponseAction = "clear"
-	RAUpdate ViewResponseAction = "update"
-	RAPush   ViewResponseAction = "push"
-	RAErrors ViewResponseAction = "errors"
-)
-
-type ViewResponseAction string
-
-type ViewSubmissionResponse struct {
-	ResponseAction ViewResponseAction `json:"response_action"`
-	View           *ModalViewRequest  `json:"view,omitempty"`
-	Errors         map[string]string  `json:"errors,omitempty"`
-}
-
-func NewClearViewSubmissionResponse() *ViewSubmissionResponse {
-	return &ViewSubmissionResponse{
-		ResponseAction: RAClear,
-	}
-}
-
-func NewUpdateViewSubmissionResponse(view *ModalViewRequest) *ViewSubmissionResponse {
-	return &ViewSubmissionResponse{
-		ResponseAction: RAUpdate,
-		View:           view,
-	}
-}
-
-func NewPushViewSubmissionResponse(view *ModalViewRequest) *ViewSubmissionResponse {
-	return &ViewSubmissionResponse{
-		ResponseAction: RAPush,
-		View:           view,
-	}
-}
-
-func NewErrorsViewSubmissionResponse(errors map[string]string) *ViewSubmissionResponse {
-	return &ViewSubmissionResponse{
-		ResponseAction: RAErrors,
-		Errors:         errors,
-	}
-}
-
 type ModalViewRequest struct {
 	Type            ViewType         `json:"type"`
 	Title           *TextBlockObject `json:"title"`
 	Blocks          Blocks           `json:"blocks"`
-	Close           *TextBlockObject `json:"close,omitempty"`
-	Submit          *TextBlockObject `json:"submit,omitempty"`
-	PrivateMetadata string           `json:"private_metadata,omitempty"`
-	CallbackID      string           `json:"callback_id,omitempty"`
-	ClearOnClose    bool             `json:"clear_on_close,omitempty"`
-	NotifyOnClose   bool             `json:"notify_on_close,omitempty"`
-	ExternalID      string           `json:"external_id,omitempty"`
+	Close           *TextBlockObject `json:"close"`
+	Submit          *TextBlockObject `json:"submit"`
+	PrivateMetadata string           `json:"private_metadata"`
+	CallbackID      string           `json:"callback_id"`
+	ClearOnClose    bool             `json:"clear_on_close"`
+	NotifyOnClose   bool             `json:"notify_on_close"`
+	ExternalID      string           `json:"external_id"`
 }
 
 func (v *ModalViewRequest) ViewType() ViewType {
@@ -108,9 +54,9 @@ func (v *ModalViewRequest) ViewType() ViewType {
 type HomeTabViewRequest struct {
 	Type            ViewType `json:"type"`
 	Blocks          Blocks   `json:"blocks"`
-	PrivateMetadata string   `json:"private_metadata,omitempty"`
-	CallbackID      string   `json:"callback_id,omitempty"`
-	ExternalID      string   `json:"external_id,omitempty"`
+	PrivateMetadata string   `json:"private_metadata"`
+	CallbackID      string   `json:"callback_id"`
+	ExternalID      string   `json:"external_id"`
 }
 
 func (v *HomeTabViewRequest) ViewType() ViewType {
@@ -125,7 +71,7 @@ type openViewRequest struct {
 type publishViewRequest struct {
 	UserID string             `json:"user_id"`
 	View   HomeTabViewRequest `json:"view"`
-	Hash   string             `json:"hash,omitempty"`
+	Hash   string             `json:"hash"`
 }
 
 type pushViewRequest struct {
@@ -135,9 +81,9 @@ type pushViewRequest struct {
 
 type updateViewRequest struct {
 	View       ModalViewRequest `json:"view"`
-	ExternalID string           `json:"external_id,omitempty"`
-	Hash       string           `json:"hash,omitempty"`
-	ViewID     string           `json:"view_id,omitempty"`
+	ExternalID string           `json:"external_id"`
+	Hash       string           `json:"hash"`
+	ViewID     string           `json:"view_id"`
 }
 
 type ViewResponse struct {
diff --git a/websocket_channels.go b/websocket_channels.go
index fe274fd..7dd3319 100644
--- a/websocket_channels.go
+++ b/websocket_channels.go
@@ -45,7 +45,7 @@ type ChannelRenameEvent struct {
 type ChannelRenameInfo struct {
 	ID      string `json:"id"`
 	Name    string `json:"name"`
-	Created int    `json:"created"`
+	Created string `json:"created"`
 }
 
 // ChannelHistoryChangedEvent represents the Channel history changed event
diff --git a/websocket_managed_conn.go b/websocket_managed_conn.go
index 8607b3a..6395938 100644
--- a/websocket_managed_conn.go
+++ b/websocket_managed_conn.go
@@ -572,12 +572,10 @@ var EventMapping = map[string]interface{}{
 	"member_joined_channel": MemberJoinedChannelEvent{},
 	"member_left_channel":   MemberLeftChannelEvent{},
 
-	"subteam_created":         SubteamCreatedEvent{},
-	"subteam_members_changed": SubteamMembersChangedEvent{},
-	"subteam_self_added":      SubteamSelfAddedEvent{},
-	"subteam_self_removed":    SubteamSelfRemovedEvent{},
-	"subteam_updated":         SubteamUpdatedEvent{},
-
-	"desktop_notification":       DesktopNotificationEvent{},
-	"mobile_in_app_notification": MobileInAppNotificationEvent{},
+	"subteam_created":      SubteamCreatedEvent{},
+	"subteam_self_added":   SubteamSelfAddedEvent{},
+	"subteam_self_removed": SubteamSelfRemovedEvent{},
+	"subteam_updated":      SubteamUpdatedEvent{},
+
+	"desktop_notification": DesktopNotificationEvent{},
 }
diff --git a/websocket_mobile_in_app_notification.go b/websocket_mobile_in_app_notification.go
deleted file mode 100644
index e3cfb3d..0000000
--- a/websocket_mobile_in_app_notification.go
+++ /dev/null
@@ -1,20 +0,0 @@
-package slack
-
-// MobileInAppNotificationEvent represents the update event for Mobile App Notification.
-type MobileInAppNotificationEvent struct {
-	Type              string `json:"type"`
-	Title             string `json:"title"`
-	Subtitle          string `json:"subtitle"`
-	Timestamp         string `json:"ts"`
-	Channel           string `json:"channel"`
-	AvatarImage       string `json:"avatarImage"`
-	IsShared          bool   `json:"is_shared"`
-	ChannelName       string `json:"channel_name"`
-	AuthorID          string `json:"author_id"`
-	AuthorDisplayName string `json:"author_display_name"`
-	MessageText       string `json:"msg_text"`
-	PushID            string `json:"push_id"`
-	NotifcationID     string `json:"notif_id"`
-	MobileLaunchURI   string `json:"mobileLaunchUri"`
-	EventTimestamp    string `json:"event_ts"`
-}


Test patch:
diff --git a/block_element_test.go b/block_element_test.go
index 651930c..d101f10 100644
--- a/block_element_test.go
+++ b/block_element_test.go
@@ -55,32 +55,6 @@ func TestNewOptionsGroupSelectBlockElement(t *testing.T) {
 
 }
 
-func TestNewOptionsMultiSelectBlockElement(t *testing.T) {
-
-	testOptionText := NewTextBlockObject("plain_text", "Option One", false, false)
-	testOption := NewOptionBlockObject("test", testOptionText)
-
-	option := NewOptionsMultiSelectBlockElement("static_select", nil, "test", testOption)
-	assert.Equal(t, option.Type, "static_select")
-	assert.Equal(t, len(option.Options), 1)
-	assert.Nil(t, option.OptionGroups)
-
-}
-
-func TestNewOptionsGroupMultiSelectBlockElement(t *testing.T) {
-
-	testOptionText := NewTextBlockObject("plain_text", "Option One", false, false)
-	testOption := NewOptionBlockObject("test", testOptionText)
-	testLabel := NewTextBlockObject("plain_text", "Test Label", false, false)
-	testGroupOption := NewOptionGroupBlockElement(testLabel, testOption)
-
-	optGroup := NewOptionsGroupMultiSelectBlockElement("static_select", nil, "test", testGroupOption)
-
-	assert.Equal(t, string(optGroup.Type), "static_select")
-	assert.Equal(t, optGroup.ActionID, "test")
-	assert.Equal(t, len(optGroup.OptionGroups), 1)
-
-}
 func TestNewOverflowBlockElement(t *testing.T) {
 
 	// Build Text Objects associated with each option
@@ -112,31 +86,8 @@ func TestNewDatePickerBlockElement(t *testing.T) {
 }
 
 func TestNewPlainTextInputBlockElement(t *testing.T) {
+	inputElement := NewPlainTextInputBlockElement(nil, "test")
 
-	plainTextInputElemnet := NewPlainTextInputBlockElement(nil, "test")
-
-	assert.Equal(t, string(plainTextInputElemnet.Type), "plain_text_input")
-	assert.Equal(t, plainTextInputElemnet.ActionID, "test")
-
-}
-
-func TestNewRadioButtonsBlockElement(t *testing.T) {
-
-	// Build Text Objects associated with each option
-	radioButtonsOptionTextOne := NewTextBlockObject("plain_text", "Option One", false, false)
-	radioButtonsOptionTextTwo := NewTextBlockObject("plain_text", "Option Two", false, false)
-	radioButtonsOptionTextThree := NewTextBlockObject("plain_text", "Option Three", false, false)
-
-	// Build each option, providing a value for the option
-	radioButtonsOptionOne := NewOptionBlockObject("value-0", radioButtonsOptionTextOne)
-	radioButtonsOptionTwo := NewOptionBlockObject("value-1", radioButtonsOptionTextTwo)
-	radioButtonsOptionThree := NewOptionBlockObject("value-2", radioButtonsOptionTextThree)
-
-	// Build overflow section
-	radioButtonsElement := NewRadioButtonsBlockElement("test", radioButtonsOptionOne, radioButtonsOptionTwo, radioButtonsOptionThree)
-
-	assert.Equal(t, string(radioButtonsElement.Type), "radio_buttons")
-	assert.Equal(t, radioButtonsElement.ActionID, "test")
-	assert.Equal(t, len(radioButtonsElement.Options), 3)
-
+	assert.Equal(t, string(inputElement.Type), "plain_text_input")
+	assert.Equal(t, inputElement.ActionID, "test")
 }
diff --git a/block_file_test.go b/block_file_test.go
deleted file mode 100644
index c51a93e..0000000
--- a/block_file_test.go
+++ /dev/null
@@ -1,15 +0,0 @@
-package slack
-
-import (
-	"testing"
-
-	"github.com/stretchr/testify/assert"
-)
-
-func TestNewFileBlock(t *testing.T) {
-	fileBlock := NewFileBlock("test", "external_id", "source")
-	assert.Equal(t, string(fileBlock.Type), "file")
-	assert.Equal(t, fileBlock.BlockID, "test")
-	assert.Equal(t, fileBlock.ExternalID, "external_id")
-	assert.Equal(t, fileBlock.Source, "source")
-}
diff --git a/block_input_test.go b/block_input_test.go
index 10c3081..ab94590 100644
--- a/block_input_test.go
+++ b/block_input_test.go
@@ -7,12 +7,11 @@ import (
 )
 
 func TestNewInputBlock(t *testing.T) {
-	label := NewTextBlockObject("plain_text", "label", false, false)
-	element := NewDatePickerBlockElement("action_id")
+	label := NewTextBlockObject("plain_text", "Input", false, false)
+	inputElement := NewPlainTextInputBlockElement(nil, "input_123")
 
-	inputBlock := NewInputBlock("test", label, element)
+	inputBlock := NewInputBlock("test", label, inputElement)
 	assert.Equal(t, string(inputBlock.Type), "input")
 	assert.Equal(t, inputBlock.BlockID, "test")
-	assert.Equal(t, inputBlock.Label, label)
-	assert.Equal(t, inputBlock.Element, element)
+	assert.Equal(t, string(inputBlock.Element.ElementType()), "plain_text_input")
 }
diff --git a/interactions_test.go b/interactions_test.go
index f9e549d..b1ad45a 100644
--- a/interactions_test.go
+++ b/interactions_test.go
@@ -9,115 +9,34 @@ import (
 
 const (
 	dialogSubmissionCallback = `{
-		"type": "dialog_submission",
-		"submission": {
-			"name": "Sigourney Dreamweaver",
-			"email": "sigdre@example.com",
-			"phone": "+1 800-555-1212",
-			"meal": "burrito",
-			"comment": "No sour cream please",
-			"team_channel": "C0LFFBKPB",
-			"who_should_sing": "U0MJRG1AL"
-		},
-		"callback_id": "employee_offsite_1138b",
-		"team": {
-			"id": "T1ABCD2E12",
-			"domain": "coverbands"
-		},
-		"user": {
-			"id": "W12A3BCDEF",
-			"name": "dreamweaver"
-		},
-		"channel": {
-			"id": "C1AB2C3DE",
-			"name": "coverthon-1999"
-		},
-		"action_ts": "936893340.702759",
-		"token": "M1AqUUw3FqayAbqNtsGMch72",
-		"response_url": "https://hooks.slack.com/app/T012AB0A1/123456789/JpmK0yzoZDeRiqfeduTBYXWQ"
-	}`
-	actionCallback     = `{}`
-	viewClosedCallback = `{
-		"type": "view_closed",
-		"team": {
-			"id": "T1ABCD2E12",
-			"domain": "coverbands"
-		},
-		"user": {
-			"id": "W12A3BCDEF",
-			"name": "dreamweaver"
-		},
-		"view": {
-			"type": "modal",
-			"title": {
-				"type": "plain_text",
-				"text": "launch project"
-			},
-			"blocks": [{
-				"type": "section",
-				"text": {
-				  "text": "*Sally* has requested you set the deadline for the Nano launch project",
-				  "type": "mrkdwn"
-				},
-				"accessory": {
-				  "type": "datepicker",
-				  "action_id": "datepicker123",
-				  "initial_date": "1990-04-28",
-				  "placeholder": {
-					"type": "plain_text",
-					"text": "Select a date"
-				  }
-				}
-			}]
-		},
-		"api_app_id": "A123ABC",
-		"is_cleared": false
-	}`
-	viewSubmissionCallback = `{
-		"type": "view_submission",
-		"team": {
-			"id": "T1ABCD2E12",
-			"domain": "coverbands"
-		},
-		"user": {
-			"id": "W12A3BCDEF",
-			"name": "dreamweaver"
-		},
-		"channel": {
-			"id": "C1AB2C3DE",
-			"name": "coverthon-1999"
-		},
-		"view": {
-			"type": "modal",
-			"title": {
-				"type": "plain_text",
-				"text": "meal choice"
-			},
-			"blocks": [{
-				"type": "input",
-				"block_id": "multi-line",
-				"label": {
-					"type": "plain_text",
-					"text": "dietary restrictions"
-				},
-				"element": {
-					"type": "plain_text_input",
-					"multiline": true,
-					"action_id": "ml-value"
-				}
-			}],
-			"state": {
-				"values": {
-					"multi-line": {
-						"ml-value": {
-							"type": "plain_text_input",
-							"value": "No onions"
-						}
-					}
-				}
-			}
-		}
-	}`
+  "type": "dialog_submission",
+  "submission": {
+      "name": "Sigourney Dreamweaver",
+      "email": "sigdre@example.com",
+      "phone": "+1 800-555-1212",
+      "meal": "burrito",
+      "comment": "No sour cream please",
+      "team_channel": "C0LFFBKPB",
+      "who_should_sing": "U0MJRG1AL"
+  },
+  "callback_id": "employee_offsite_1138b",
+  "team": {
+      "id": "T1ABCD2E12",
+      "domain": "coverbands"
+  },
+  "user": {
+      "id": "W12A3BCDEF",
+      "name": "dreamweaver"
+  },
+  "channel": {
+      "id": "C1AB2C3DE",
+      "name": "coverthon-1999"
+  },
+  "action_ts": "936893340.702759",
+  "token": "M1AqUUw3FqayAbqNtsGMch72",
+  "response_url": "https://hooks.slack.com/app/T012AB0A1/123456789/JpmK0yzoZDeRiqfeduTBYXWQ"
+}`
+	actionCallback = `{}`
 )
 
 func assertInteractionCallback(t *testing.T, callback InteractionCallback, encoded string) {
@@ -165,89 +84,6 @@ func TestActionCallback(t *testing.T) {
 	assertInteractionCallback(t, InteractionCallback{}, actionCallback)
 }
 
-func TestViewClosedck(t *testing.T) {
-	expected := InteractionCallback{
-		Type: InteractionTypeViewClosed,
-		Team: Team{ID: "T1ABCD2E12", Name: "", Domain: "coverbands"},
-		User: User{
-			ID:   "W12A3BCDEF",
-			Name: "dreamweaver",
-		},
-		View: View{
-			Type:  VTModal,
-			Title: NewTextBlockObject("plain_text", "launch project", false, false),
-			Blocks: Blocks{
-				BlockSet: []Block{
-					NewSectionBlock(
-						NewTextBlockObject("mrkdwn", "*Sally* has requested you set the deadline for the Nano launch project", false, false),
-						nil,
-						NewAccessory(&DatePickerBlockElement{
-							Type:        METDatepicker,
-							ActionID:    "datepicker123",
-							InitialDate: "1990-04-28",
-							Placeholder: NewTextBlockObject("plain_text", "Select a date", false, false),
-						}),
-					),
-				},
-			},
-		},
-		APIAppID: "A123ABC",
-	}
-	assertInteractionCallback(t, expected, viewClosedCallback)
-}
-
-func TestViewSubmissionCallback(t *testing.T) {
-	expected := InteractionCallback{
-		Type: InteractionTypeViewSubmission,
-		Team: Team{ID: "T1ABCD2E12", Name: "", Domain: "coverbands"},
-		Channel: Channel{
-			GroupConversation: GroupConversation{
-				Conversation: Conversation{
-					ID: "C1AB2C3DE",
-				},
-				Name: "coverthon-1999",
-			},
-		},
-		User: User{
-			ID:   "W12A3BCDEF",
-			Name: "dreamweaver",
-		},
-		View: View{
-			Type:  VTModal,
-			Title: NewTextBlockObject("plain_text", "meal choice", false, false),
-			Blocks: Blocks{
-				BlockSet: []Block{
-					NewInputBlock(
-						"multi-line",
-						NewTextBlockObject(
-							"plain_text",
-							"dietary restrictions",
-							false,
-							false,
-						),
-						&PlainTextInputBlockElement{
-							Type:      "plain_text_input",
-							ActionID:  "ml-value",
-							Multiline: true,
-						},
-					),
-				},
-			},
-			State: &ViewState{
-				Values: map[string]map[string]BlockAction{
-					"multi-line": map[string]BlockAction{
-						"ml-value": BlockAction{
-							Type:  "plain_text_input",
-							Value: "No onions",
-						},
-					},
-				},
-			},
-		},
-	}
-	assertInteractionCallback(t, expected, viewSubmissionCallback)
-}
-
 func TestInteractionCallbackJSONMarshalAndUnmarshal(t *testing.T) {
 	cb := &InteractionCallback{
 		Type:        InteractionTypeBlockActions,
@@ -256,33 +92,14 @@ func TestInteractionCallbackJSONMarshalAndUnmarshal(t *testing.T) {
 		ResponseURL: "responseURL",
 		TriggerID:   "triggerID",
 		ActionTs:    "actionTS",
-		Team: Team{
-			ID:   "teamid",
-			Name: "teamname",
-		},
-		Channel: Channel{
-			GroupConversation: GroupConversation{
-				Name:         "channelname",
-				Conversation: Conversation{ID: "channelid"},
-			},
-		},
-		User: User{
-			ID:      "userid",
-			Name:    "username",
-			Profile: UserProfile{RealName: "userrealname"},
-		},
-		OriginalMessage: Message{
-			Msg: Msg{
-				Text:      "ogmsg text",
-				Timestamp: "ogmsg ts",
-			},
-		},
-		Message: Message{
-			Msg: Msg{
-				Text:      "text",
-				Timestamp: "ts",
-			},
-		},
+		Team:        Team{ID: "teamid", Name: "teamname"},
+		Channel: Channel{GroupConversation: GroupConversation{
+			Name: "channelname", Conversation: Conversation{ID: "channelid"}}},
+		User: User{ID: "userid", Name: "username",
+			Profile: UserProfile{RealName: "userrealname"}},
+		OriginalMessage: Message{Msg: Msg{Text: "ogmsg text",
+			Timestamp: "ogmsg ts"}},
+		Message:      Message{Msg: Msg{Text: "text", Timestamp: "ts"}},
 		Name:         "name",
 		Value:        "value",
 		MessageTs:    "messageTs",
@@ -291,13 +108,6 @@ func TestInteractionCallbackJSONMarshalAndUnmarshal(t *testing.T) {
 			AttachmentActions: []*AttachmentAction{{Value: "value"}},
 			BlockActions:      []*BlockAction{{ActionID: "id123"}},
 		},
-		View: View{
-			Type:  VTModal,
-			Title: NewTextBlockObject("plain_text", "title", false, false),
-			Blocks: Blocks{
-				BlockSet: []Block{NewDividerBlock()},
-			},
-		},
 		DialogSubmissionCallback: DialogSubmissionCallback{State: "dsstate"},
 	}
 
@@ -335,9 +145,6 @@ func TestInteractionCallbackJSONMarshalAndUnmarshal(t *testing.T) {
 		len(jsonCB.ActionCallback.AttachmentActions))
 	assert.Equal(t, len(cb.ActionCallback.BlockActions),
 		len(jsonCB.ActionCallback.BlockActions))
-	assert.Equal(t, cb.View.Type, jsonCB.View.Type)
-	assert.Equal(t, cb.View.Title, jsonCB.View.Title)
-	assert.Equal(t, cb.View.Blocks, jsonCB.View.Blocks)
 	assert.Equal(t, cb.DialogSubmissionCallback.State,
 		jsonCB.DialogSubmissionCallback.State)
 }
diff --git a/slackevents/inner_events_test.go b/slackevents/inner_events_test.go
index d73f8f6..44d2646 100644
--- a/slackevents/inner_events_test.go
+++ b/slackevents/inner_events_test.go
@@ -14,7 +14,10 @@ func TestAppMention(t *testing.T) {
 				"ts": "1515449522.000016",
 				"thread_ts": "1515449522.000016",
 				"channel": "C0LAN2Q65",
-				"event_ts": "1515449522000016"
+				"event_ts": "1515449522000016",
+				"source_team": "T3MQV36V7",
+				"user_team": "T3MQV36V7",
+				"blah": "test"
 		}
 	`)
 	err := json.Unmarshal(rawE, &AppMentionEvent{})
@@ -109,6 +112,8 @@ func TestMessageEvent(t *testing.T) {
 				"ts": "1355517523.000005",
 				"event_ts": "1355517523.000005",
 				"channel_type": "channel",
+				"source_team": "T3MQV36V7",
+				"user_team": "T3MQV36V7",
 				"message": {
 					"text": "To infinity and beyond.",
 					"edited": {
diff --git a/views_test.go b/views_test.go
index ce91da3..561c8ce 100644
--- a/views_test.go
+++ b/views_test.go
@@ -1,12 +1,10 @@
 package slack
 
 import (
-	"encoding/json"
 	"net/http"
 	"testing"
 
 	"github.com/slack-go/slack/internal/errorsx"
-	"github.com/stretchr/testify/assert"
 )
 
 var dummySlackErr = errorsx.String("dummy_error_from_slack")
@@ -96,7 +94,7 @@ func TestSlack_OpenView(t *testing.T) {
 					"callback_id": "identify_your_modals",
 					"external_id": "",
 					"state": {
-						"values": {}
+						"values": []
 					},
 					"hash": "156772938.1827394",
 					"clear_on_close": false,
@@ -213,7 +211,7 @@ func TestSlack_View_PublishView(t *testing.T) {
 					"private_metadata": "Shh it is a secret",
 					"callback_id": "identify_your_home_tab",
 					"state": {
-						"values": {}
+						"values": []
 					},
 					"hash": "156772938.1827394",
 					"clear_on_close": false,
@@ -344,7 +342,7 @@ func TestSlack_PushView(t *testing.T) {
 					"callback_id": "identify_your_modals",
 					"external_id": "",
 					"state": {
-						"values": {}
+						"values": []
 					},
 					"hash": "156772938.1827394",
 					"clear_on_close": false,
@@ -477,7 +475,7 @@ func TestSlack_UpdateView(t *testing.T) {
 					"callback_id": "identify_your_modals",
 					"external_id": "",
 					"state": {
-						"values": {}
+						"values": []
 					},
 					"hash": "156772938.1827394",
 					"clear_on_close": false,
@@ -529,107 +527,3 @@ func TestSlack_UpdateView(t *testing.T) {
 		})
 	}
 }
-
-func assertViewSubmissionResponse(t *testing.T, resp *ViewSubmissionResponse, encoded string) {
-	var decoded *ViewSubmissionResponse
-	assert.Nil(t, json.Unmarshal([]byte(encoded), &decoded))
-	assert.Equal(t, decoded, resp)
-}
-
-func TestSlack_ClearViewSubmissionResponse(t *testing.T) {
-	resp := NewClearViewSubmissionResponse()
-	rawResp := `{
-		"response_action": "clear"
-	}`
-
-	assertViewSubmissionResponse(t, resp, rawResp)
-}
-
-func TestSlack_UpdateViewSubmissionResponse(t *testing.T) {
-	resp := NewUpdateViewSubmissionResponse(&ModalViewRequest{
-		Type:   VTModal,
-		Title:  NewTextBlockObject("plain_text", "Test update view submission response", false, false),
-		Blocks: Blocks{BlockSet: []Block{NewFileBlock("file_block_id", "external_string", "source_string")}},
-	})
-	rawResp := `{
-		"response_action": "update",
-		"view": {
-			"type": "modal",
-			"title": {
-				"type": "plain_text",
-				"text": "Test update view submission response"
-			},
-			"blocks": [
-				{
-					"type": "file",
-					"block_id": "file_block_id",
-					"external_id": "external_string",
-					"source": "source_string"
-				}
-			]
-		}
-	}`
-
-	assertViewSubmissionResponse(t, resp, rawResp)
-}
-
-func TestSlack_PushViewSubmissionResponse(t *testing.T) {
-	resp := NewPushViewSubmissionResponse(&ModalViewRequest{
-		Type:  VTModal,
-		Title: NewTextBlockObject("plain_text", "Test update view submission response", false, false),
-		Blocks: Blocks{
-			BlockSet: []Block{
-				NewContextBlock(
-					"context_block_id",
-					NewTextBlockObject("plain_text", "Context text", false, false),
-					NewImageBlockElement("image_url", "alt_text"),
-				),
-			},
-		},
-	})
-	rawResp := `{
-		"response_action": "push",
-		"view": {
-			"type": "modal",
-			"title": {
-				"type": "plain_text",
-				"text": "Test update view submission response"
-			},
-			"blocks": [
-				{
-					"type": "context",
-					"block_id": "context_block_id",
-					"elements": [
-						{
-							"type": "plain_text",
-							"text": "Context text"
-						},
-						{
-							"type": "image",
-							"image_url": "image_url",
-							"alt_text": "alt_text"
-						}
-					]
-				}
-			]
-		}
-	}`
-
-	assertViewSubmissionResponse(t, resp, rawResp)
-}
-
-func TestSlack_ErrorsViewSubmissionResponse(t *testing.T) {
-	resp := NewErrorsViewSubmissionResponse(map[string]string{
-		"input_text_action_id": "Please input a name that's at least 6 characters long",
-		"file_action_id":       "File exceeded size limit of 5 KB",
-	})
-	rawResp := `{
-		"response_action": "errors",
-		"errors": {
-			"input_text_action_id": "Please input a name that's at least 6 characters long",
-			"file_action_id": "File exceeded size limit of 5 KB"
-		}
-	}`
-
-	assertViewSubmissionResponse(t, resp, rawResp)
-}