Skip to content

Commit f39c68c

Browse files
authored
fix!: AppHomeOpenedEvent View is now a pointer (#1424)
According to #1421, if there was never an app home view published, the event `app_home_opened` won't have a view keyword in the inner event. BREAKING CHANGE: Moving `View` to a pointer with `omitempty`, should fix this but also makes this fix a breaking change.
2 parents 61734c3 + c2d9312 commit f39c68c

File tree

4 files changed

+232
-30
lines changed

4 files changed

+232
-30
lines changed

examples/conversations/conversations.go

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,13 @@ import (
88
)
99

1010
func main() {
11-
botToken := os.Getenv("SLACK_BOT_TOKEN")
12-
if botToken == "" {
13-
fmt.Fprintf(os.Stderr, "SLACK_BOT_TOKEN must be set.\n")
11+
userToken := os.Getenv("SLACK_USER_TOKEN")
12+
if userToken == "" {
13+
fmt.Fprintf(os.Stderr, "SLACK_USER_TOKEN must be set.\n")
1414
os.Exit(1)
1515
}
1616

17-
api := slack.New(botToken)
17+
api := slack.New(userToken)
1818
params := slack.GetConversationsParameters{
1919
ExcludeArchived: true,
2020
Limit: 100,
@@ -25,6 +25,19 @@ func main() {
2525
return
2626
}
2727
for _, channel := range channels {
28-
fmt.Printf("Channel: %v\n", channel)
28+
info, err := api.GetConversationInfo(&slack.GetConversationInfoInput{
29+
ChannelID: channel.ID,
30+
IncludeNumMembers: true,
31+
IncludeLocale: true,
32+
})
33+
if err != nil {
34+
fmt.Printf("Error getting info for channel %s: %s\n", channel.ID, err)
35+
continue
36+
}
37+
fmt.Printf("Channel: %s\n", channel.ID)
38+
if info.Properties != nil {
39+
fmt.Printf("Canvas: %+v\n", info.Properties.Canvas)
40+
fmt.Printf("Tabs: %+v\n", info.Properties.Tabs)
41+
}
2942
}
3043
}

examples/users/users.go

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,19 @@ package main
22

33
import (
44
"fmt"
5+
"os"
56

67
"github.com/slack-go/slack"
78
)
89

910
func main() {
10-
api := slack.New("YOUR_TOKEN_HERE")
11+
userToken := os.Getenv("SLACK_USER_TOKEN")
12+
if userToken == "" {
13+
fmt.Fprintf(os.Stderr, "SLACK_USER_TOKEN must be set.\n")
14+
os.Exit(1)
15+
}
16+
17+
api := slack.New(userToken)
1118
user, err := api.GetUserInfo("U023BECGF")
1219
if err != nil {
1320
fmt.Printf("%s\n", err)

slackevents/inner_events.go

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -66,12 +66,12 @@ type AppMentionEvent struct {
6666

6767
// AppHomeOpenedEvent Your Slack app home was opened.
6868
type AppHomeOpenedEvent struct {
69-
Type string `json:"type"`
70-
User string `json:"user"`
71-
Channel string `json:"channel"`
72-
EventTimeStamp string `json:"event_ts"`
73-
Tab string `json:"tab"`
74-
View slack.View `json:"view"`
69+
Type string `json:"type"`
70+
User string `json:"user"`
71+
Channel string `json:"channel"`
72+
EventTimeStamp string `json:"event_ts"`
73+
Tab string `json:"tab"`
74+
View *slack.View `json:"view,omitempty"`
7575
}
7676

7777
// AppUninstalledEvent Your Slack app was uninstalled.

slackevents/inner_events_test.go

Lines changed: 200 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import (
55
"fmt"
66
"testing"
77

8+
"github.com/slack-go/slack"
89
"github.com/stretchr/testify/assert"
910
)
1011

@@ -15,9 +16,9 @@ func TestAssistantThreadStartedEvent(t *testing.T) {
1516
"type": "assistant_thread_started",
1617
"assistant_thread": {
1718
"user_id": "U123ABC456",
18-
"context": {
19-
"channel_id": "C123ABC456",
20-
"team_id": "T07XY8FPJ5C",
19+
"context": {
20+
"channel_id": "C123ABC456",
21+
"team_id": "T07XY8FPJ5C",
2122
"enterprise_id": "E480293PS82"
2223
},
2324
"channel_id": "D123ABC456",
@@ -42,9 +43,9 @@ func TestAssistantThreadContextChangedEvent(t *testing.T) {
4243
"type": "assistant_thread_context_changed",
4344
"assistant_thread": {
4445
"user_id": "U123ABC456",
45-
"context": {
46-
"channel_id": "C123ABC456",
47-
"team_id": "T07XY8FPJ5C",
46+
"context": {
47+
"channel_id": "C123ABC456",
48+
"team_id": "T07XY8FPJ5C",
4849
"enterprise_id": "E480293PS82"
4950
},
5051
"channel_id": "D123ABC456",
@@ -725,10 +726,10 @@ func TestMessageMetadataPosted(t *testing.T) {
725726
{
726727
"type":"message_metadata_posted",
727728
"app_id":"APPXXX",
728-
"bot_id":"BOTXXX",
729-
"user_id":"USERXXX",
730-
"team_id":"TEAMXXX",
731-
"channel_id":"CHANNELXXX",
729+
"bot_id":"BOTXXX",
730+
"user_id":"USERXXX",
731+
"team_id":"TEAMXXX",
732+
"channel_id":"CHANNELXXX",
732733
"metadata":{
733734
"event_type":"type",
734735
"event_payload":{"key": "value"}
@@ -781,16 +782,16 @@ func TestMessageMetadataUpdated(t *testing.T) {
781782
rawE := []byte(`
782783
{
783784
"type":"message_metadata_updated",
784-
"channel_id":"CHANNELXXX",
785+
"channel_id":"CHANNELXXX",
785786
"event_ts":"1660398079.756349",
786787
"previous_metadata":{
787788
"event_type":"type1",
788789
"event_payload":{"key1": "value1"}
789790
},
790791
"app_id":"APPXXX",
791-
"bot_id":"BOTXXX",
792-
"user_id":"USERXXX",
793-
"team_id":"TEAMXXX",
792+
"bot_id":"BOTXXX",
793+
"user_id":"USERXXX",
794+
"team_id":"TEAMXXX",
794795
"message_ts":"1660398079.756349",
795796
"metadata":{
796797
"event_type":"type2",
@@ -849,16 +850,16 @@ func TestMessageMetadataDeleted(t *testing.T) {
849850
rawE := []byte(`
850851
{
851852
"type":"message_metadata_deleted",
852-
"channel_id":"CHANNELXXX",
853+
"channel_id":"CHANNELXXX",
853854
"event_ts":"1660398079.756349",
854855
"previous_metadata":{
855856
"event_type":"type",
856857
"event_payload":{"key": "value"}
857858
},
858859
"app_id":"APPXXX",
859-
"bot_id":"BOTXXX",
860-
"user_id":"USERXXX",
861-
"team_id":"TEAMXXX",
860+
"bot_id":"BOTXXX",
861+
"user_id":"USERXXX",
862+
"team_id":"TEAMXXX",
862863
"message_ts":"1660398079.756349",
863864
"deleted_ts":"1660398079.756349"
864865
}
@@ -2771,3 +2772,184 @@ func TestSharedChannelInviteRequested_UnmarshalJSON(t *testing.T) {
27712772
t.Errorf("Expected second team to have name 'another_enterprise', got '%v'", event.TeamsInChannel)
27722773
}
27732774
}
2775+
2776+
func TestAppHomeOpenedEvent_WithView(t *testing.T) {
2777+
eventJSON := []byte(`{
2778+
"type": "app_home_opened",
2779+
"user": "U12345678",
2780+
"channel": "D12345678",
2781+
"tab": "home",
2782+
"event_ts": "1747319568.267214",
2783+
"view": {
2784+
"id": "V12345678",
2785+
"team_id": "T12345678",
2786+
"type": "home",
2787+
"blocks": [],
2788+
"private_metadata": "",
2789+
"callback_id": "",
2790+
"state": {
2791+
"values": {}
2792+
},
2793+
"hash": "1234567890.abcdef",
2794+
"title": {
2795+
"type": "plain_text",
2796+
"text": "App Home"
2797+
},
2798+
"clear_on_close": false,
2799+
"notify_on_close": false,
2800+
"close": null,
2801+
"submit": null,
2802+
"previous_view_id": "",
2803+
"root_view_id": "V12345678",
2804+
"app_id": "A12345678",
2805+
"external_id": "",
2806+
"app_installed_team_id": "T12345678",
2807+
"bot_id": "B12345678"
2808+
}
2809+
}`)
2810+
2811+
var event AppHomeOpenedEvent
2812+
err := json.Unmarshal(eventJSON, &event)
2813+
2814+
assert.NoError(t, err)
2815+
assert.Equal(t, "app_home_opened", event.Type)
2816+
assert.Equal(t, "U12345678", event.User)
2817+
assert.Equal(t, "D12345678", event.Channel)
2818+
assert.Equal(t, "home", event.Tab)
2819+
assert.Equal(t, "1747319568.267214", event.EventTimeStamp)
2820+
assert.NotNil(t, event.View)
2821+
assert.Equal(t, "V12345678", event.View.ID)
2822+
assert.Equal(t, "T12345678", event.View.TeamID)
2823+
assert.Equal(t, slack.ViewType("home"), event.View.Type)
2824+
}
2825+
2826+
func TestAppHomeOpenedEvent_WithoutView(t *testing.T) {
2827+
eventJSON := []byte(`{
2828+
"type": "app_home_opened",
2829+
"user": "U12345678",
2830+
"channel": "D12345678",
2831+
"tab": "home",
2832+
"event_ts": "1747319568.267214"
2833+
}`)
2834+
2835+
var event AppHomeOpenedEvent
2836+
err := json.Unmarshal(eventJSON, &event)
2837+
2838+
assert.NoError(t, err)
2839+
assert.Equal(t, "app_home_opened", event.Type)
2840+
assert.Equal(t, "U12345678", event.User)
2841+
assert.Equal(t, "D12345678", event.Channel)
2842+
assert.Equal(t, "home", event.Tab)
2843+
assert.Equal(t, "1747319568.267214", event.EventTimeStamp)
2844+
assert.Nil(t, event.View)
2845+
}
2846+
2847+
func TestAppHomeOpenedEvent_FullEventParsing_WithView(t *testing.T) {
2848+
fullEventJSON := []byte(`{
2849+
"token": "verification-token",
2850+
"team_id": "T12345678",
2851+
"api_app_id": "A12345678",
2852+
"event": {
2853+
"type": "app_home_opened",
2854+
"user": "U12345678",
2855+
"channel": "D12345678",
2856+
"tab": "home",
2857+
"event_ts": "1747319568.267214",
2858+
"view": {
2859+
"id": "V12345678",
2860+
"team_id": "T12345678",
2861+
"type": "home",
2862+
"blocks": [],
2863+
"private_metadata": "",
2864+
"callback_id": "",
2865+
"state": {
2866+
"values": {}
2867+
},
2868+
"hash": "1234567890.abcdef",
2869+
"title": {
2870+
"type": "plain_text",
2871+
"text": "App Home"
2872+
},
2873+
"clear_on_close": false,
2874+
"notify_on_close": false,
2875+
"close": null,
2876+
"submit": null,
2877+
"previous_view_id": "",
2878+
"root_view_id": "V12345678",
2879+
"app_id": "A12345678",
2880+
"external_id": "",
2881+
"app_installed_team_id": "T12345678",
2882+
"bot_id": "B12345678"
2883+
}
2884+
},
2885+
"type": "event_callback",
2886+
"event_id": "Ev12345678",
2887+
"event_time": 1747319568,
2888+
"authorizations": [{
2889+
"enterprise_id": null,
2890+
"team_id": "T12345678",
2891+
"user_id": "U12345678",
2892+
"is_bot": true,
2893+
"is_enterprise_install": false
2894+
}],
2895+
"is_ext_shared_channel": false
2896+
}`)
2897+
2898+
parsedEvent, err := ParseEvent(fullEventJSON, OptionNoVerifyToken())
2899+
2900+
assert.NoError(t, err)
2901+
assert.Equal(t, "T12345678", parsedEvent.TeamID)
2902+
assert.Equal(t, "A12345678", parsedEvent.APIAppID)
2903+
assert.Equal(t, "app_home_opened", parsedEvent.InnerEvent.Type)
2904+
appHomeEvent, ok := parsedEvent.InnerEvent.Data.(*AppHomeOpenedEvent)
2905+
assert.True(t, ok)
2906+
assert.Equal(t, "app_home_opened", appHomeEvent.Type)
2907+
assert.Equal(t, "U12345678", appHomeEvent.User)
2908+
assert.Equal(t, "D12345678", appHomeEvent.Channel)
2909+
assert.Equal(t, "home", appHomeEvent.Tab)
2910+
assert.Equal(t, "1747319568.267214", appHomeEvent.EventTimeStamp)
2911+
assert.NotNil(t, appHomeEvent.View)
2912+
assert.Equal(t, "V12345678", appHomeEvent.View.ID)
2913+
assert.Equal(t, "T12345678", appHomeEvent.View.TeamID)
2914+
}
2915+
2916+
func TestAppHomeOpenedEvent_FullEventParsing_WithoutView(t *testing.T) {
2917+
fullEventJSON := []byte(`{
2918+
"token": "verification-token",
2919+
"team_id": "T12345678",
2920+
"api_app_id": "A12345678",
2921+
"event": {
2922+
"type": "app_home_opened",
2923+
"user": "U12345678",
2924+
"channel": "D12345678",
2925+
"tab": "home",
2926+
"event_ts": "1747319568.267214"
2927+
},
2928+
"type": "event_callback",
2929+
"event_id": "Ev12345678",
2930+
"event_time": 1747319568,
2931+
"authorizations": [{
2932+
"enterprise_id": null,
2933+
"team_id": "T12345678",
2934+
"user_id": "U12345678",
2935+
"is_bot": true,
2936+
"is_enterprise_install": false
2937+
}],
2938+
"is_ext_shared_channel": false
2939+
}`)
2940+
2941+
parsedEvent, err := ParseEvent(fullEventJSON, OptionNoVerifyToken())
2942+
2943+
assert.NoError(t, err)
2944+
assert.Equal(t, "T12345678", parsedEvent.TeamID)
2945+
assert.Equal(t, "A12345678", parsedEvent.APIAppID)
2946+
assert.Equal(t, "app_home_opened", parsedEvent.InnerEvent.Type)
2947+
appHomeEvent, ok := parsedEvent.InnerEvent.Data.(*AppHomeOpenedEvent)
2948+
assert.True(t, ok)
2949+
assert.Equal(t, "app_home_opened", appHomeEvent.Type)
2950+
assert.Equal(t, "U12345678", appHomeEvent.User)
2951+
assert.Equal(t, "D12345678", appHomeEvent.Channel)
2952+
assert.Equal(t, "home", appHomeEvent.Tab)
2953+
assert.Equal(t, "1747319568.267214", appHomeEvent.EventTimeStamp)
2954+
assert.Nil(t, appHomeEvent.View)
2955+
}

0 commit comments

Comments
 (0)