Skip to content

Commit

Permalink
Merge pull request #820 from slack-go/modify-state
Browse files Browse the repository at this point in the history
Handle state in interaction callback
  • Loading branch information
kanata2 committed Oct 11, 2020
2 parents 26dd6eb + ac7b9d0 commit da8fd1f
Show file tree
Hide file tree
Showing 3 changed files with 105 additions and 2 deletions.
4 changes: 3 additions & 1 deletion dialog.go
Expand Up @@ -54,7 +54,9 @@ type DialogCallback InteractionCallback

// DialogSubmissionCallback is sent from Slack when a user submits a form from within a dialog
type DialogSubmissionCallback struct {
State string `json:"state,omitempty"`
// NOTE: State is only used with the dialog_submission type.
// You should use InteractionCallback.BlockActionsState for block_actions type.
State string `json:"-"`
Submission map[string]string `json:"submission"`
}

Expand Down
57 changes: 57 additions & 0 deletions interactions.go
Expand Up @@ -56,6 +56,63 @@ type InteractionCallback struct {
DialogSubmissionCallback
ViewSubmissionCallback
ViewClosedCallback

// FIXME(kanata2): just workaround for backward-compatibility.
// See also https://github.com/slack-go/slack/issues/816
RawState json.RawMessage `json:"state,omitempty"`

// BlockActionState stands for the `state` field in block_actions type.
// NOTE: InteractionCallback.State has a role for the state of dialog_submission type,
// so we cannot use this field for backward-compatibility for now.
BlockActionState *BlockActionStates `json:"-"`
}

type BlockActionStates struct {
Values map[string]map[string]BlockAction `json:"values"`
}

func (ic *InteractionCallback) MarshalJSON() ([]byte, error) {
type alias InteractionCallback
tmp := alias(*ic)
if tmp.Type == InteractionTypeBlockActions {
if tmp.BlockActionState == nil {
tmp.RawState = []byte(`{}`)
} else {
state, err := json.Marshal(tmp.BlockActionState.Values)
if err != nil {
return nil, err
}
tmp.RawState = []byte(`{"values":` + string(state) + `}`)
}
} else if ic.Type == InteractionTypeDialogSubmission {
tmp.RawState = []byte(tmp.State)
}
// Use pointer for go1.7
return json.Marshal(&tmp)
}

func (ic *InteractionCallback) UnmarshalJSON(b []byte) error {
type alias InteractionCallback
tmp := struct {
Type InteractionType `json:"type"`
*alias
}{
alias: (*alias)(ic),
}
if err := json.Unmarshal(b, &tmp); err != nil {
return err
}
*ic = InteractionCallback(*tmp.alias)
ic.Type = tmp.Type
if ic.Type == InteractionTypeBlockActions {
err := json.Unmarshal(ic.RawState, &ic.BlockActionState)
if err != nil {
return err
}
} else if ic.Type == InteractionTypeDialogSubmission {
ic.State = string(ic.RawState)
}
return nil
}

type Container struct {
Expand Down
46 changes: 45 additions & 1 deletion interactions_test.go
Expand Up @@ -304,7 +304,8 @@ func TestInteractionCallbackJSONMarshalAndUnmarshal(t *testing.T) {
BlockSet: []Block{NewDividerBlock()},
},
},
DialogSubmissionCallback: DialogSubmissionCallback{State: "dsstate"},
DialogSubmissionCallback: DialogSubmissionCallback{State: ""},
RawState: json.RawMessage(`{}`),
}

cbJSONBytes, err := json.Marshal(cb)
Expand Down Expand Up @@ -347,3 +348,46 @@ func TestInteractionCallbackJSONMarshalAndUnmarshal(t *testing.T) {
assert.Equal(t, cb.DialogSubmissionCallback.State,
jsonCB.DialogSubmissionCallback.State)
}

func TestInteractionCallback_InteractionTypeBlockActions_Unmarshal(t *testing.T) {
raw := []byte(`{
"type": "block_actions",
"actions": [
{
"type": "multi_conversations_select",
"action_id": "multi_convos",
"block_id": "test123",
"selected_conversations": ["G12345"]
}
],
"container": {
"type": "view",
"view_id": "V12345"
},
"state": {
"values": {
"section_block_id": {
"multi_convos": {
"type": "multi_conversations_select",
"selected_conversations": ["G12345"]
}
},
"other_block_id": {
"other_action_id": {
"type": "plain_text_input",
"value": "test123"
}
}
}
}
}`)
var cb InteractionCallback
assert.NoError(t, json.Unmarshal(raw, &cb))
assert.Equal(t, cb.State, "")
assert.Equal(t,
cb.BlockActionState.Values["section_block_id"]["multi_convos"].actionType(),
actionType(MultiOptTypeConversations))
assert.Equal(t,
cb.BlockActionState.Values["section_block_id"]["multi_convos"].SelectedConversations,
[]string{"G12345"})
}

0 comments on commit da8fd1f

Please sign in to comment.