diff --git a/dialog.go b/dialog.go index 376cd9e60..f94113f4d 100644 --- a/dialog.go +++ b/dialog.go @@ -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"` } diff --git a/interactions.go b/interactions.go index c7f592171..34ab9f745 100644 --- a/interactions.go +++ b/interactions.go @@ -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 { diff --git a/interactions_test.go b/interactions_test.go index 6298a5ac3..c4f98b88d 100644 --- a/interactions_test.go +++ b/interactions_test.go @@ -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) @@ -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"}) +}