From e947079302882b182ee1bfae177023405fb747a2 Mon Sep 17 00:00:00 2001 From: Arya Khochare <91268931+Aryakoste@users.noreply.github.com> Date: Thu, 15 Aug 2024 22:41:50 +0530 Subject: [PATCH] feat: Events api reconcilation (#1306) * events added with test * added events with tests * added all events and changes done --- slackevents/inner_events.go | 646 +++++++++++++++-- slackevents/inner_events_test.go | 1149 ++++++++++++++++++++++++++++++ 2 files changed, 1752 insertions(+), 43 deletions(-) diff --git a/slackevents/inner_events.go b/slackevents/inner_events.go index 391bd3b4b..8f8effaae 100644 --- a/slackevents/inner_events.go +++ b/slackevents/inner_events.go @@ -652,6 +652,462 @@ type SharedInvite struct { IsExternalLimited bool `json:"is_external_limited,omitempty"` } +type ChannelHistoryChangedEvent struct { + Type string `json:"type"` + Latest string `json:"latest"` + Ts string `json:"ts"` + EventTs string `json:"event_ts"` +} + +type CommandsChangedEvent struct { + Type string `json:"type"` + EventTs string `json:"event_ts"` +} + +type DndUpdatedEvent struct { + Type string `json:"type"` + User string `json:"user"` + DndStatus struct { + DndEnabled bool `json:"dnd_enabled"` + NextDndStartTs int64 `json:"next_dnd_start_ts"` + NextDndEndTs int64 `json:"next_dnd_end_ts"` + SnoozeEnabled bool `json:"snooze_enabled"` + SnoozeEndtime int64 `json:"snooze_endtime"` + } `json:"dnd_status"` +} + +type DndUpdatedUserEvent struct { + Type string `json:"type"` + User string `json:"user"` + DndStatus struct { + DndEnabled bool `json:"dnd_enabled"` + NextDndStartTs int64 `json:"next_dnd_start_ts"` + NextDndEndTs int64 `json:"next_dnd_end_ts"` + } `json:"dnd_status"` +} + +type EmailDomainChangedEvent struct { + Type string `json:"type"` + EmailDomain string `json:"email_domain"` + EventTs string `json:"event_ts"` +} + +type GroupCloseEvent struct { + Type string `json:"type"` + User string `json:"user"` + Channel string `json:"channel"` +} + +type GroupHistoryChangedEvent struct { + Type string `json:"type"` + Latest string `json:"latest"` + Ts string `json:"ts"` + EventTs string `json:"event_ts"` +} + +type GroupOpenEvent struct { + Type string `json:"type"` + User string `json:"user"` + Channel string `json:"channel"` +} + +type ImCloseEvent struct { + Type string `json:"type"` + User string `json:"user"` + Channel string `json:"channel"` +} + +type ImCreatedEvent struct { + Type string `json:"type"` + User string `json:"user"` + Channel struct { + ID string `json:"id"` + } `json:"channel"` +} + +type ImHistoryChangedEvent struct { + Type string `json:"type"` + Latest string `json:"latest"` + Ts string `json:"ts"` + EventTs string `json:"event_ts"` +} + +type ImOpenEvent struct { + Type string `json:"type"` + User string `json:"user"` + Channel string `json:"channel"` +} + +type SubTeam struct { + ID string `json:"id"` + TeamID string `json:"team_id"` + IsUsergroup bool `json:"is_usergroup"` + Name string `json:"name"` + Description string `json:"description"` + Handle string `json:"handle"` + IsExternal bool `json:"is_external"` + DateCreate int64 `json:"date_create"` + DateUpdate int64 `json:"date_update"` + DateDelete int64 `json:"date_delete"` + AutoType string `json:"auto_type"` + CreatedBy string `json:"created_by"` + UpdatedBy string `json:"updated_by"` + DeletedBy string `json:"deleted_by"` + Prefs struct { + Channels []string `json:"channels"` + Groups []string `json:"groups"` + } `json:"prefs"` + Users []string `json:"users"` + UserCount int `json:"user_count"` +} + +type SubteamCreatedEvent struct { + Type string `json:"type"` + Subteam SubTeam `json:"subteam"` +} + +type SubteamMembersChangedEvent struct { + Type string `json:"type"` + SubteamID string `json:"subteam_id"` + TeamID string `json:"team_id"` + DatePreviousUpdate int `json:"date_previous_update"` + DateUpdate int64 `json:"date_update"` + AddedUsers []string `json:"added_users"` + AddedUsersCount string `json:"added_users_count"` + RemovedUsers []string `json:"removed_users"` + RemovedUsersCount string `json:"removed_users_count"` +} + +type SubteamSelfAddedEvent struct { + Type string `json:"type"` + SubteamID string `json:"subteam_id"` +} + +type SubteamSelfRemovedEvent struct { + Type string `json:"type"` + SubteamID string `json:"subteam_id"` +} + +type SubteamUpdatedEvent struct { + Type string `json:"type"` + Subteam SubTeam `json:"subteam"` +} + +type TeamDomainChangeEvent struct { + Type string `json:"type"` + URL string `json:"url"` + Domain string `json:"domain"` + TeamID string `json:"team_id"` +} + +type TeamRenameEvent struct { + Type string `json:"type"` + Name string `json:"name"` + TeamID string `json:"team_id"` +} + +type UserChangeEvent struct { + Type string `json:"type"` + User User `json:"user"` + CacheTS int64 `json:"cache_ts"` + EventTS string `json:"event_ts"` +} + +type AppDeletedEvent struct { + Type string `json:"type"` + AppID string `json:"app_id"` + AppName string `json:"app_name"` + AppOwnerID string `json:"app_owner_id"` + TeamID string `json:"team_id"` + TeamDomain string `json:"team_domain"` + EventTs string `json:"event_ts"` +} + +type AppInstalledEvent struct { + Type string `json:"type"` + AppID string `json:"app_id"` + AppName string `json:"app_name"` + AppOwnerID string `json:"app_owner_id"` + UserID string `json:"user_id"` + TeamID string `json:"team_id"` + TeamDomain string `json:"team_domain"` + EventTs string `json:"event_ts"` +} + +type AppRequestedEvent struct { + Type string `json:"type"` + AppRequest struct { + ID string `json:"id"` + App struct { + ID string `json:"id"` + Name string `json:"name"` + Description string `json:"description"` + HelpURL string `json:"help_url"` + PrivacyPolicyURL string `json:"privacy_policy_url"` + AppHomepageURL string `json:"app_homepage_url"` + AppDirectoryURL string `json:"app_directory_url"` + IsAppDirectoryApproved bool `json:"is_app_directory_approved"` + IsInternal bool `json:"is_internal"` + AdditionalInfo string `json:"additional_info"` + } `json:"app"` + PreviousResolution struct { + Status string `json:"status"` + Scopes []struct { + Name string `json:"name"` + Description string `json:"description"` + IsSensitive bool `json:"is_sensitive"` + TokenType string `json:"token_type"` + } `json:"scopes"` + } `json:"previous_resolution"` + User struct { + ID string `json:"id"` + Name string `json:"name"` + Email string `json:"email"` + } `json:"user"` + Team struct { + ID string `json:"id"` + Name string `json:"name"` + Domain string `json:"domain"` + } `json:"team"` + Enterprise interface{} `json:"enterprise"` + Scopes []struct { + Name string `json:"name"` + Description string `json:"description"` + IsSensitive bool `json:"is_sensitive"` + TokenType string `json:"token_type"` + } `json:"scopes"` + Message string `json:"message"` + } `json:"app_request"` +} + +type AppUninstalledTeamEvent struct { + Type string `json:"type"` + AppID string `json:"app_id"` + AppName string `json:"app_name"` + AppOwnerID string `json:"app_owner_id"` + UserID string `json:"user_id"` + TeamID string `json:"team_id"` + TeamDomain string `json:"team_domain"` + EventTs string `json:"event_ts"` +} + +type CallRejectedEvent struct { + Token string `json:"token"` + TeamID string `json:"team_id"` + APIAppID string `json:"api_app_id"` + Event struct { + Type string `json:"type"` + CallID string `json:"call_id"` + UserID string `json:"user_id"` + ChannelID string `json:"channel_id"` + ExternalUniqueID string `json:"external_unique_id"` + } `json:"event"` + Type string `json:"type"` + EventID string `json:"event_id"` + AuthedUsers []string `json:"authed_users"` +} + +type ChannelSharedEvent struct { + Type string `json:"type"` + ConnectedTeamID string `json:"connected_team_id"` + Channel string `json:"channel"` + EventTs string `json:"event_ts"` +} + +type FileCreatedEvent struct { + Type string `json:"type"` + FileID string `json:"file_id"` + File struct { + ID string `json:"id"` + } `json:"file"` +} + +type FilePublicEvent struct { + Type string `json:"type"` + FileID string `json:"file_id"` + File struct { + ID string `json:"id"` + } `json:"file"` +} + +type FunctionExecutedEvent struct { + Type string `json:"type"` + Function struct { + ID string `json:"id"` + CallbackID string `json:"callback_id"` + Title string `json:"title"` + Description string `json:"description"` + Type string `json:"type"` + InputParameters []struct { + Type string `json:"type"` + Name string `json:"name"` + Description string `json:"description"` + Title string `json:"title"` + IsRequired bool `json:"is_required"` + } `json:"input_parameters"` + OutputParameters []struct { + Type string `json:"type"` + Name string `json:"name"` + Description string `json:"description"` + Title string `json:"title"` + IsRequired bool `json:"is_required"` + } `json:"output_parameters"` + AppID string `json:"app_id"` + DateCreated int64 `json:"date_created"` + DateUpdated int64 `json:"date_updated"` + DateDeleted int64 `json:"date_deleted"` + } `json:"function"` + Inputs map[string]string `json:"inputs"` + FunctionExecutionID string `json:"function_execution_id"` + WorkflowExecutionID string `json:"workflow_execution_id"` + EventTs string `json:"event_ts"` + BotAccessToken string `json:"bot_access_token"` +} + +type InviteRequestedEvent struct { + Type string `json:"type"` + InviteRequest struct { + ID string `json:"id"` + Email string `json:"email"` + DateCreated int64 `json:"date_created"` + RequesterIDs []string `json:"requester_ids"` + ChannelIDs []string `json:"channel_ids"` + InviteType string `json:"invite_type"` + RealName string `json:"real_name"` + DateExpire int64 `json:"date_expire"` + RequestReason string `json:"request_reason"` + Team struct { + ID string `json:"id"` + Name string `json:"name"` + Domain string `json:"domain"` + } `json:"team"` + } `json:"invite_request"` +} + +type StarAddedEvent struct { + Type string `json:"type"` + User string `json:"user"` + Item struct { + } `json:"item"` + EventTS string `json:"event_ts"` +} + +type StarRemovedEvent struct { + Type string `json:"type"` + User string `json:"user"` + Item struct { + } `json:"item"` + EventTS string `json:"event_ts"` +} + +type UserHuddleChangedEvent struct { + Type string `json:"type"` + User User `json:"user"` + CacheTS int64 `json:"cache_ts"` + EventTS string `json:"event_ts"` +} + +type User struct { + ID string `json:"id"` + TeamID string `json:"team_id"` + Name string `json:"name"` + Deleted bool `json:"deleted"` + Color string `json:"color"` + RealName string `json:"real_name"` + TZ string `json:"tz"` + TZLabel string `json:"tz_label"` + TZOffset int `json:"tz_offset"` + Profile Profile `json:"profile"` + IsAdmin bool `json:"is_admin"` + IsOwner bool `json:"is_owner"` + IsPrimaryOwner bool `json:"is_primary_owner"` + IsRestricted bool `json:"is_restricted"` + IsUltraRestricted bool `json:"is_ultra_restricted"` + IsBot bool `json:"is_bot"` + IsAppUser bool `json:"is_app_user"` + Updated int64 `json:"updated"` + IsEmailConfirmed bool `json:"is_email_confirmed"` + WhoCanShareContactCard string `json:"who_can_share_contact_card"` + Locale string `json:"locale"` +} + +type Profile struct { + Title string `json:"title"` + Phone string `json:"phone"` + Skype string `json:"skype"` + RealName string `json:"real_name"` + RealNameNormalized string `json:"real_name_normalized"` + DisplayName string `json:"display_name"` + DisplayNameNormalized string `json:"display_name_normalized"` + Fields map[string]interface{} `json:"fields"` + StatusText string `json:"status_text"` + StatusEmoji string `json:"status_emoji"` + StatusEmojiDisplayInfo []interface{} `json:"status_emoji_display_info"` + StatusExpiration int `json:"status_expiration"` + AvatarHash string `json:"avatar_hash"` + FirstName string `json:"first_name"` + LastName string `json:"last_name"` + Image24 string `json:"image_24"` + Image32 string `json:"image_32"` + Image48 string `json:"image_48"` + Image72 string `json:"image_72"` + Image192 string `json:"image_192"` + Image512 string `json:"image_512"` + StatusTextCanonical string `json:"status_text_canonical"` + Team string `json:"team"` +} + +type UserStatusChangedEvent struct { + Type string `json:"type"` + User User `json:"user"` + CacheTS int64 `json:"cache_ts"` + EventTS string `json:"event_ts"` +} + +type Actor struct { + ID string `json:"id"` + Name string `json:"name"` + IsBot bool `json:"is_bot"` + TeamID string `json:"team_id"` + Timezone string `json:"timezone"` + RealName string `json:"real_name"` + DisplayName string `json:"display_name"` +} + +type TargetUser struct { + Email string `json:"email"` + InviteID string `json:"invite_id"` +} + +type TeamIcon struct { + Image34 string `json:"image_34"` + ImageDefault bool `json:"image_default"` +} + +type Team struct { + ID string `json:"id"` + Icon TeamIcon `json:"icon"` + Name string `json:"name"` + Domain string `json:"domain"` + IsVerified bool `json:"is_verified"` + DateCreated int64 `json:"date_created"` + AvatarBaseURL string `json:"avatar_base_url"` + RequiresSponsorship bool `json:"requires_sponsorship"` +} + +type SharedChannelInviteRequestedEvent struct { + Actor Actor `json:"actor"` + ChannelID string `json:"channel_id"` + EventType string `json:"event_type"` + ChannelName string `json:"channel_name"` + ChannelType string `json:"channel_type"` + TargetUsers []TargetUser `json:"target_users"` + TeamsInChannel []Team `json:"teams_in_channel"` + IsExternalLimited bool `json:"is_external_limited"` + ChannelDateCreated int64 `json:"channel_date_created"` + ChannelMessageLatestCounted int64 `json:"channel_message_latest_counted_timestamp"` +} + type EventsAPIType string const ( @@ -741,53 +1197,157 @@ const ( TeamAccessRevoked = EventsAPIType("team_access_revoked") // UserProfileChanged is sent if a user's profile information has changed. UserProfileChanged = EventsAPIType("user_profile_changed") + // ChannelHistoryChanged The history of a channel changed + ChannelHistoryChanged = EventsAPIType("channel_history_changed") + // CommandsChanged A command was changed + CommandsChanged = EventsAPIType("commands_changed") + // DndUpdated Do Not Disturb settings were updated + DndUpdated = EventsAPIType("dnd_updated") + // DndUpdatedUser Do Not Disturb settings for a user were updated + DndUpdatedUser = EventsAPIType("dnd_updated_user") + // EmailDomainChanged The email domain changed + EmailDomainChanged = EventsAPIType("email_domain_changed") + // GroupClose A group was closed + GroupClose = EventsAPIType("group_close") + // GroupHistoryChanged The history of a group changed + GroupHistoryChanged = EventsAPIType("group_history_changed") + // GroupOpen A group was opened + GroupOpen = EventsAPIType("group_open") + // ImClose An instant message channel was closed + ImClose = EventsAPIType("im_close") + // ImCreated An instant message channel was created + ImCreated = EventsAPIType("im_created") + // ImHistoryChanged The history of an instant message channel changed + ImHistoryChanged = EventsAPIType("im_history_changed") + // ImOpen An instant message channel was opened + ImOpen = EventsAPIType("im_open") + // SubteamCreated A subteam was created + SubteamCreated = EventsAPIType("subteam_created") + // SubteamMembersChanged The members of a subteam changed + SubteamMembersChanged = EventsAPIType("subteam_members_changed") + // SubteamSelfAdded The current user was added to a subteam + SubteamSelfAdded = EventsAPIType("subteam_self_added") + // SubteamSelfRemoved The current user was removed from a subteam + SubteamSelfRemoved = EventsAPIType("subteam_self_removed") + // SubteamUpdated A subteam was updated + SubteamUpdated = EventsAPIType("subteam_updated") + // TeamDomainChange The team's domain changed + TeamDomainChange = EventsAPIType("team_domain_change") + // TeamRename The team was renamed + TeamRename = EventsAPIType("team_rename") + // UserChange A user object has changed + UserChange = EventsAPIType("user_change") + // AppDeleted is an event when an app is deleted from a workspace + AppDeleted = EventsAPIType("app_deleted") + // AppInstalled is an event when an app is installed to a workspace + AppInstalled = EventsAPIType("app_installed") + // AppRequested is an event when a user requests to install an app to a workspace + AppRequested = EventsAPIType("app_requested") + // AppUninstalledTeam is an event when an app is uninstalled from a team + AppUninstalledTeam = EventsAPIType("app_uninstalled_team") + // CallRejected is an event when a Slack call is rejected + CallRejected = EventsAPIType("call_rejected") + // ChannelShared is an event when a channel is shared with another workspace + ChannelShared = EventsAPIType("channel_shared") + // FileCreated is an event when a file is created in a workspace + FileCreated = EventsAPIType("file_created") + // FilePublic is an event when a file is made public in a workspace + FilePublic = EventsAPIType("file_public") + // FunctionExecuted is an event when a Slack function is executed + FunctionExecuted = EventsAPIType("function_executed") + // InviteRequested is an event when a user requests an invite to a workspace + InviteRequested = EventsAPIType("invite_requested") + // SharedChannelInviteRequested is an event when an invitation to share a channel is requested + SharedChannelInviteRequested = EventsAPIType("shared_channel_invite_requested") + // StarAdded is an event when a star is added to a message or file + StarAdded = EventsAPIType("star_added") + // StarRemoved is an event when a star is removed from a message or file + StarRemoved = EventsAPIType("star_removed") + // UserHuddleChanged is an event when a user's huddle status changes + UserHuddleChanged = EventsAPIType("user_huddle_changed") + // UserStatusChanged is an event when a user's status changes + UserStatusChanged = EventsAPIType("user_status_changed") ) // EventsAPIInnerEventMapping maps INNER Event API events to their corresponding struct // implementations. The structs should be instances of the unmarshalling // target for the matching event type. var EventsAPIInnerEventMapping = map[EventsAPIType]interface{}{ - AppMention: AppMentionEvent{}, - AppHomeOpened: AppHomeOpenedEvent{}, - AppUninstalled: AppUninstalledEvent{}, - ChannelCreated: ChannelCreatedEvent{}, - ChannelDeleted: ChannelDeletedEvent{}, - ChannelArchive: ChannelArchiveEvent{}, - ChannelUnarchive: ChannelUnarchiveEvent{}, - ChannelLeft: ChannelLeftEvent{}, - ChannelRename: ChannelRenameEvent{}, - ChannelIDChanged: ChannelIDChangedEvent{}, - FileChange: FileChangeEvent{}, - FileDeleted: FileDeletedEvent{}, - FileShared: FileSharedEvent{}, - FileUnshared: FileUnsharedEvent{}, - GroupDeleted: GroupDeletedEvent{}, - GroupArchive: GroupArchiveEvent{}, - GroupUnarchive: GroupUnarchiveEvent{}, - GroupLeft: GroupLeftEvent{}, - GroupRename: GroupRenameEvent{}, - GridMigrationFinished: GridMigrationFinishedEvent{}, - GridMigrationStarted: GridMigrationStartedEvent{}, - LinkShared: LinkSharedEvent{}, - Message: MessageEvent{}, - MemberJoinedChannel: MemberJoinedChannelEvent{}, - MemberLeftChannel: MemberLeftChannelEvent{}, - PinAdded: PinAddedEvent{}, - PinRemoved: PinRemovedEvent{}, - ReactionAdded: ReactionAddedEvent{}, - ReactionRemoved: ReactionRemovedEvent{}, - SharedChannelInviteApproved: SharedChannelInviteApprovedEvent{}, - SharedChannelInviteAccepted: SharedChannelInviteAcceptedEvent{}, - SharedChannelInviteDeclined: SharedChannelInviteDeclinedEvent{}, - SharedChannelInviteReceived: SharedChannelInviteReceivedEvent{}, - TeamJoin: TeamJoinEvent{}, - TokensRevoked: TokensRevokedEvent{}, - EmojiChanged: EmojiChangedEvent{}, - WorkflowStepExecute: WorkflowStepExecuteEvent{}, - MessageMetadataPosted: MessageMetadataPostedEvent{}, - MessageMetadataUpdated: MessageMetadataUpdatedEvent{}, - MessageMetadataDeleted: MessageMetadataDeletedEvent{}, - TeamAccessGranted: TeamAccessGrantedEvent{}, - TeamAccessRevoked: TeamAccessRevokedEvent{}, - UserProfileChanged: UserProfileChangedEvent{}, + AppMention: AppMentionEvent{}, + AppHomeOpened: AppHomeOpenedEvent{}, + AppUninstalled: AppUninstalledEvent{}, + ChannelCreated: ChannelCreatedEvent{}, + ChannelDeleted: ChannelDeletedEvent{}, + ChannelArchive: ChannelArchiveEvent{}, + ChannelUnarchive: ChannelUnarchiveEvent{}, + ChannelLeft: ChannelLeftEvent{}, + ChannelRename: ChannelRenameEvent{}, + ChannelIDChanged: ChannelIDChangedEvent{}, + FileChange: FileChangeEvent{}, + FileDeleted: FileDeletedEvent{}, + FileShared: FileSharedEvent{}, + FileUnshared: FileUnsharedEvent{}, + GroupDeleted: GroupDeletedEvent{}, + GroupArchive: GroupArchiveEvent{}, + GroupUnarchive: GroupUnarchiveEvent{}, + GroupLeft: GroupLeftEvent{}, + GroupRename: GroupRenameEvent{}, + GridMigrationFinished: GridMigrationFinishedEvent{}, + GridMigrationStarted: GridMigrationStartedEvent{}, + LinkShared: LinkSharedEvent{}, + Message: MessageEvent{}, + MemberJoinedChannel: MemberJoinedChannelEvent{}, + MemberLeftChannel: MemberLeftChannelEvent{}, + PinAdded: PinAddedEvent{}, + PinRemoved: PinRemovedEvent{}, + ReactionAdded: ReactionAddedEvent{}, + ReactionRemoved: ReactionRemovedEvent{}, + SharedChannelInviteApproved: SharedChannelInviteApprovedEvent{}, + SharedChannelInviteAccepted: SharedChannelInviteAcceptedEvent{}, + SharedChannelInviteDeclined: SharedChannelInviteDeclinedEvent{}, + SharedChannelInviteReceived: SharedChannelInviteReceivedEvent{}, + TeamJoin: TeamJoinEvent{}, + TokensRevoked: TokensRevokedEvent{}, + EmojiChanged: EmojiChangedEvent{}, + WorkflowStepExecute: WorkflowStepExecuteEvent{}, + MessageMetadataPosted: MessageMetadataPostedEvent{}, + MessageMetadataUpdated: MessageMetadataUpdatedEvent{}, + MessageMetadataDeleted: MessageMetadataDeletedEvent{}, + TeamAccessGranted: TeamAccessGrantedEvent{}, + TeamAccessRevoked: TeamAccessRevokedEvent{}, + UserProfileChanged: UserProfileChangedEvent{}, + ChannelHistoryChanged: ChannelHistoryChangedEvent{}, + DndUpdated: DndUpdatedEvent{}, + DndUpdatedUser: DndUpdatedUserEvent{}, + EmailDomainChanged: EmailDomainChangedEvent{}, + GroupClose: GroupCloseEvent{}, + GroupHistoryChanged: GroupHistoryChangedEvent{}, + GroupOpen: GroupOpenEvent{}, + ImClose: ImCloseEvent{}, + ImCreated: ImCreatedEvent{}, + ImHistoryChanged: ImHistoryChangedEvent{}, + ImOpen: ImOpenEvent{}, + SubteamCreated: SubteamCreatedEvent{}, + SubteamMembersChanged: SubteamMembersChangedEvent{}, + SubteamSelfAdded: SubteamSelfAddedEvent{}, + SubteamSelfRemoved: SubteamSelfRemovedEvent{}, + SubteamUpdated: SubteamUpdatedEvent{}, + TeamDomainChange: TeamDomainChangeEvent{}, + TeamRename: TeamRenameEvent{}, + UserChange: UserChangeEvent{}, + AppDeleted: AppDeletedEvent{}, + AppInstalled: AppInstalledEvent{}, + AppRequested: AppRequestedEvent{}, + AppUninstalledTeam: AppUninstalledTeamEvent{}, + CallRejected: CallRejectedEvent{}, + ChannelShared: ChannelSharedEvent{}, + FileCreated: FileCreatedEvent{}, + FilePublic: FilePublicEvent{}, + FunctionExecuted: FunctionExecutedEvent{}, + InviteRequested: InviteRequestedEvent{}, + SharedChannelInviteRequested: SharedChannelInviteRequestedEvent{}, + StarAdded: StarAddedEvent{}, + StarRemoved: StarRemovedEvent{}, + UserHuddleChanged: UserHuddleChangedEvent{}, + UserStatusChanged: UserStatusChangedEvent{}, } diff --git a/slackevents/inner_events_test.go b/slackevents/inner_events_test.go index 71eb402f8..4307e8ad6 100644 --- a/slackevents/inner_events_test.go +++ b/slackevents/inner_events_test.go @@ -1504,3 +1504,1152 @@ func TestSharedChannelDeclined(t *testing.T) { } } + +func TestChannelHistoryChangedEvent(t *testing.T) { + rawE := []byte(` + { + "type": "channel_history_changed", + "latest": "1358877455.000010", + "ts": "1358877455.000008", + "event_ts": "1358877455.000011" + } + `) + + var e ChannelHistoryChangedEvent + if err := json.Unmarshal(rawE, &e); err != nil { + t.Fatal(err) + } + if e.Type != "channel_history_changed" { + t.Errorf("type should be channel_history_changed, was %s", e.Type) + } + if e.Latest != "1358877455.000010" { + t.Errorf("latest should be 1358877455.000010, was %s", e.Latest) + } + if e.Ts != "1358877455.000008" { + t.Errorf("ts should be 1358877455.000008, was %s", e.Ts) + } + if e.EventTs != "1358877455.000011" { + t.Errorf("event_ts should be 1358877455.000011, was %s", e.EventTs) + } +} + +func TestDndUpdatedEvent(t *testing.T) { + rawE := []byte(` + { + "type": "dnd_updated", + "user": "U1234567890", + "dnd_status": { + "dnd_enabled": true, + "next_dnd_start_ts": 1624473600, + "next_dnd_end_ts": 1624516800, + "snooze_enabled": false + } + } + `) + + var e DndUpdatedEvent + if err := json.Unmarshal(rawE, &e); err != nil { + t.Fatal(err) + } + if e.Type != "dnd_updated" { + t.Errorf("type should be dnd_updated, was %s", e.Type) + } + if e.User != "U1234567890" { + t.Errorf("user should be U1234567890, was %s", e.User) + } + if !e.DndStatus.DndEnabled { + t.Errorf("dnd_enabled should be true, was %v", e.DndStatus.DndEnabled) + } + if e.DndStatus.NextDndStartTs != 1624473600 { + t.Errorf("next_dnd_start_ts should be 1624473600, was %d", e.DndStatus.NextDndStartTs) + } + if e.DndStatus.NextDndEndTs != 1624516800 { + t.Errorf("next_dnd_end_ts should be 1624516800, was %d", e.DndStatus.NextDndEndTs) + } + if e.DndStatus.SnoozeEnabled { + t.Errorf("snooze_enabled should be false, was %v", e.DndStatus.SnoozeEnabled) + } +} + +func TestDndUpdatedUserEvent(t *testing.T) { + rawE := []byte(` + { + "type": "dnd_updated_user", + "user": "U1234", + "dnd_status": { + "dnd_enabled": true, + "next_dnd_start_ts": 1450387800, + "next_dnd_end_ts": 1450423800 + } + } + `) + + var e DndUpdatedUserEvent + if err := json.Unmarshal(rawE, &e); err != nil { + t.Fatal(err) + } + if e.Type != "dnd_updated_user" { + t.Errorf("type should be dnd_updated_user, was %s", e.Type) + } + if e.User != "U1234" { + t.Errorf("user should be U1234, was %s", e.User) + } + if !e.DndStatus.DndEnabled { + t.Errorf("dnd_enabled should be true, was %v", e.DndStatus.DndEnabled) + } + if e.DndStatus.NextDndStartTs != 1450387800 { + t.Errorf("next_dnd_start_ts should be 1450387800, was %d", e.DndStatus.NextDndStartTs) + } + if e.DndStatus.NextDndEndTs != 1450423800 { + t.Errorf("next_dnd_end_ts should be 1450423800, was %d", e.DndStatus.NextDndEndTs) + } +} + +func TestEmailDomainChangedEvent(t *testing.T) { + rawE := []byte(` + { + "type": "email_domain_changed", + "email_domain": "example.com", + "event_ts": "1234567890.123456" + } + `) + + var e EmailDomainChangedEvent + if err := json.Unmarshal(rawE, &e); err != nil { + t.Fatal(err) + } + if e.Type != "email_domain_changed" { + t.Errorf("type should be email_domain_changed, was %s", e.Type) + } + if e.EmailDomain != "example.com" { + t.Errorf("email_domain should be example.com, was %s", e.EmailDomain) + } + if e.EventTs != "1234567890.123456" { + t.Errorf("event_ts should be 1234567890.123456, was %s", e.EventTs) + } +} + +func TestGroupHistoryChangedEvent(t *testing.T) { + rawE := []byte(` + { + "type": "group_history_changed", + "latest": "1358877455.000010", + "ts": "1361482916.000003", + "event_ts": "1361482916.000004" + } + `) + + var e GroupHistoryChangedEvent + if err := json.Unmarshal(rawE, &e); err != nil { + t.Fatal(err) + } + if e.Type != "group_history_changed" { + t.Errorf("type should be group_history_changed, was %s", e.Type) + } + if e.Latest != "1358877455.000010" { + t.Errorf("latest should be 1358877455.000010, was %s", e.Latest) + } + if e.Ts != "1361482916.000003" { + t.Errorf("ts should be 1361482916.000003, was %s", e.Ts) + } +} + +func TestGroupOpenEvent(t *testing.T) { + rawE := []byte(` + { + "type": "group_open", + "user": "U024BE7LH", + "channel": "G024BE91L" + } + `) + + var e GroupOpenEvent + if err := json.Unmarshal(rawE, &e); err != nil { + t.Fatal(err) + } + if e.Type != "group_open" { + t.Errorf("type should be group_open, was %s", e.Type) + } + if e.User != "U024BE7LH" { + t.Errorf("user should be U024BE7LH, was %s", e.User) + } + if e.Channel != "G024BE91L" { + t.Errorf("channel should be G024BE91L, was %s", e.Channel) + } +} + +func TestGroupCloseEvent(t *testing.T) { + rawE := []byte(` + { + "type": "group_close", + "user": "U1234567890", + "channel": "G1234567890" + } + `) + + var e GroupCloseEvent + if err := json.Unmarshal(rawE, &e); err != nil { + t.Fatal(err) + } + if e.Type != "group_close" { + t.Errorf("type should be group_close, was %s", e.Type) + } + if e.User != "U1234567890" { + t.Errorf("user should be U1234567890, was %s", e.User) + } + if e.Channel != "G1234567890" { + t.Errorf("channel should be G1234567890, was %s", e.Channel) + } +} + +func TestImCloseEvent(t *testing.T) { + rawE := []byte(` + { + "type": "im_close", + "user": "U1234567890", + "channel": "D1234567890" + } + `) + + var e ImCloseEvent + if err := json.Unmarshal(rawE, &e); err != nil { + t.Fatal(err) + } + if e.Type != "im_close" { + t.Errorf("type should be im_close, was %s", e.Type) + } + if e.User != "U1234567890" { + t.Errorf("user should be U1234567890, was %s", e.User) + } + if e.Channel != "D1234567890" { + t.Errorf("channel should be D1234567890, was %s", e.Channel) + } +} + +func TestImCreatedEvent(t *testing.T) { + rawE := []byte(` + { + "type": "im_created", + "user": "U1234567890", + "channel": { + "id": "C12345678" + } + } + `) + + var e ImCreatedEvent + if err := json.Unmarshal(rawE, &e); err != nil { + t.Fatal(err) + } + if e.Type != "im_created" { + t.Errorf("type should be im_created, was %s", e.Type) + } + if e.User != "U1234567890" { + t.Errorf("user should be U1234567890, was %s", e.User) + } + if e.Channel.ID != "C12345678" { + t.Errorf("channel.id should be C12345678, was %s", e.Channel.ID) + } +} + +func TestImHistoryChangedEvent(t *testing.T) { + rawE := []byte(` + { + "type": "im_history_changed", + "latest": "1358877455.000010", + "ts": "1361482916.000003", + "event_ts": "1361482916.000004" + } + `) + + var e ImHistoryChangedEvent + if err := json.Unmarshal(rawE, &e); err != nil { + t.Fatal(err) + } + if e.Type != "im_history_changed" { + t.Errorf("type should be im_created, was %s", e.Type) + } + if e.Latest != "1358877455.000010" { + t.Errorf("latest should be 1358877455.000010, was %s", e.Latest) + } + if e.Ts != "1361482916.000003" { + t.Errorf("ts should be 1361482916.000003, was %s", e.Ts) + } + if e.EventTs != "1361482916.000004" { + t.Errorf("event_ts should be 1361482916.000004, was %s", e.EventTs) + } +} + +func TestImOpenEvent(t *testing.T) { + rawE := []byte(` + { + "type": "im_open", + "user": "U1234567890", + "channel": "D1234567890" + } + `) + + var e ImOpenEvent + if err := json.Unmarshal(rawE, &e); err != nil { + t.Fatal(err) + } + if e.Type != "im_open" { + t.Errorf("type should be im_open, was %s", e.Type) + } + if e.User != "U1234567890" { + t.Errorf("user should be U1234567890, was %s", e.User) + } + if e.Channel != "D1234567890" { + t.Errorf("channel should be D1234567890, was %s", e.Channel) + } +} + +func TestSubteamCreatedEvent(t *testing.T) { + rawE := []byte(` + { + "type": "subteam_created", + "subteam": { + "id": "S1234567890", + "team_id": "T1234567890", + "is_usergroup": true, + "name": "subteam", + "description": "A test subteam", + "handle": "subteam_handle", + "is_external": false, + "date_create": 1624473600, + "date_update": 1624473600, + "date_delete": 0, + "auto_type": "auto", + "created_by": "U1234567890", + "updated_by": "U1234567890", + "deleted_by": "", + "prefs": { + "channels": ["C1234567890"], + "groups": ["G1234567890"] + }, + "users": ["U1234567890"], + "user_count": 1 + } + } + `) + + var e SubteamCreatedEvent + if err := json.Unmarshal(rawE, &e); err != nil { + t.Fatal(err) + } + if e.Type != "subteam_created" { + t.Errorf("type should be subteam_created, was %s", e.Type) + } + if e.Subteam.ID != "S1234567890" { + t.Errorf("subteam.id should be S1234567890, was %s", e.Subteam.ID) + } + if e.Subteam.TeamID != "T1234567890" { + t.Errorf("subteam.team_id should be T1234567890, was %s", e.Subteam.TeamID) + } + if !e.Subteam.IsUsergroup { + t.Errorf("subteam.is_usergroup should be true, was %v", e.Subteam.IsUsergroup) + } + if e.Subteam.Name != "subteam" { + t.Errorf("subteam.name should be subteam, was %s", e.Subteam.Name) + } + if e.Subteam.Description != "A test subteam" { + t.Errorf("subteam.description should be 'A test subteam', was %s", e.Subteam.Description) + } + if e.Subteam.Handle != "subteam_handle" { + t.Errorf("subteam.handle should be subteam_handle, was %s", e.Subteam.Handle) + } + if e.Subteam.IsExternal { + t.Errorf("subteam.is_external should be false, was %v", e.Subteam.IsExternal) + } + if e.Subteam.DateCreate != 1624473600 { + t.Errorf("subteam.date_create should be 1624473600, was %d", e.Subteam.DateCreate) + } + if e.Subteam.DateUpdate != 1624473600 { + t.Errorf("subteam.date_update should be 1624473600, was %d", e.Subteam.DateUpdate) + } + if e.Subteam.DateDelete != 0 { + t.Errorf("subteam.date_delete should be 0, was %d", e.Subteam.DateDelete) + } + if e.Subteam.AutoType != "auto" { + t.Errorf("subteam.auto_type should be auto, was %s", e.Subteam.AutoType) + } + if e.Subteam.CreatedBy != "U1234567890" { + t.Errorf("subteam.created_by should be U1234567890, was %s", e.Subteam.CreatedBy) + } + if e.Subteam.UpdatedBy != "U1234567890" { + t.Errorf("subteam.updated_by should be U1234567890, was %s", e.Subteam.UpdatedBy) + } + if e.Subteam.DeletedBy != "" { + t.Errorf("subteam.deleted_by should be empty, was %s", e.Subteam.DeletedBy) + } + if len(e.Subteam.Prefs.Channels) != 1 || e.Subteam.Prefs.Channels[0] != "C1234567890" { + t.Errorf("subteam.prefs.channels should contain C1234567890, was %v", e.Subteam.Prefs.Channels) + } + if len(e.Subteam.Prefs.Groups) != 1 || e.Subteam.Prefs.Groups[0] != "G1234567890" { + t.Errorf("subteam.prefs.groups should contain G1234567890, was %v", e.Subteam.Prefs.Groups) + } + if len(e.Subteam.Users) != 1 || e.Subteam.Users[0] != "U1234567890" { + t.Errorf("subteam.users should contain U1234567890, was %v", e.Subteam.Users) + } + if e.Subteam.UserCount != 1 { + t.Errorf("subteam.user_count should be 1, was %d", e.Subteam.UserCount) + } +} + +func TestSubteamMembersChangedEvent(t *testing.T) { + rawE := []byte(` + { + "type": "subteam_members_changed", + "subteam_id": "S1234567890", + "team_id": "T1234567890", + "date_previous_update": 1446670362, + "date_update": 1624473600, + "added_users": ["U1234567890"], + "added_users_count": "3", + "removed_users": ["U0987654321"], + "removed_users_count": "1" + } + `) + + var e SubteamMembersChangedEvent + if err := json.Unmarshal(rawE, &e); err != nil { + t.Fatal(err) + } + if e.Type != "subteam_members_changed" { + t.Errorf("type should be subteam_members_changed, was %s", e.Type) + } + if e.SubteamID != "S1234567890" { + t.Errorf("subteam_id should be S1234567890, was %s", e.SubteamID) + } + if e.TeamID != "T1234567890" { + t.Errorf("team_id should be T1234567890, was %s", e.TeamID) + } + if e.DateUpdate != 1624473600 { + t.Errorf("date_update should be 1624473600, was %d", e.DateUpdate) + } + if len(e.AddedUsers) != 1 || e.AddedUsers[0] != "U1234567890" { + t.Errorf("subteam.users should contain U1234567890, was %v", e.AddedUsers) + } + if len(e.RemovedUsers) != 1 || e.RemovedUsers[0] != "U0987654321" { + t.Errorf("subteam.users should contain U0987654321, was %v", e.RemovedUsers) + } +} + +func TestSubteamSelfAddedEvent(t *testing.T) { + rawE := []byte(` + { + "type": "subteam_self_added", + "subteam_id": "S1234567890" + } + `) + + var e SubteamSelfAddedEvent + if err := json.Unmarshal(rawE, &e); err != nil { + t.Fatal(err) + } + if e.Type != "subteam_self_added" { + t.Errorf("type should be subteam_self_added, was %s", e.Type) + } + if e.SubteamID != "S1234567890" { + t.Errorf("subteam_id should be S1234567890, was %s", e.SubteamID) + } +} + +func TestSubteamSelfRemovedEvent(t *testing.T) { + rawE := []byte(` + { + "type": "subteam_self_removed", + "subteam_id": "S1234567890" + } + `) + + var e SubteamSelfRemovedEvent + if err := json.Unmarshal(rawE, &e); err != nil { + t.Fatal(err) + } + if e.Type != "subteam_self_removed" { + t.Errorf("type should be subteam_self_removed, was %s", e.Type) + } + if e.SubteamID != "S1234567890" { + t.Errorf("subteam_id should be S1234567890, was %s", e.SubteamID) + } +} + +func TestSubteamUpdatedEvent(t *testing.T) { + rawE := []byte(` + { + "type": "subteam_updated", + "subteam": { + "id": "S1234567890", + "team_id": "T1234567890", + "is_usergroup": true, + "name": "updated_subteam", + "description": "An updated test subteam", + "handle": "updated_subteam_handle", + "is_external": false, + "date_create": 1624473600, + "date_update": 1624473600, + "date_delete": 0, + "auto_type": "auto", + "created_by": "U1234567890", + "updated_by": "U1234567890", + "deleted_by": "", + "prefs": { + "channels": ["C1234567890"], + "groups": ["G1234567890"] + }, + "users": ["U1234567890"], + "user_count": 1 + } + } + `) + + var e SubteamUpdatedEvent + if err := json.Unmarshal(rawE, &e); err != nil { + t.Fatal(err) + } + if e.Type != "subteam_updated" { + t.Errorf("type should be subteam_updated, was %s", e.Type) + } + if e.Subteam.ID != "S1234567890" { + t.Errorf("subteam.id should be S1234567890, was %s", e.Subteam.ID) + } + if e.Subteam.TeamID != "T1234567890" { + t.Errorf("subteam.team_id should be T1234567890, was %s", e.Subteam.TeamID) + } + if !e.Subteam.IsUsergroup { + t.Errorf("subteam.is_usergroup should be true, was %v", e.Subteam.IsUsergroup) + } + if e.Subteam.Name != "updated_subteam" { + t.Errorf("subteam.name should be updated_subteam, was %s", e.Subteam.Name) + } + if e.Subteam.Description != "An updated test subteam" { + t.Errorf("subteam.description should be 'An updated test subteam', was %s", e.Subteam.Description) + } + if e.Subteam.Handle != "updated_subteam_handle" { + t.Errorf("subteam.handle should be updated_subteam_handle, was %s", e.Subteam.Handle) + } + if e.Subteam.IsExternal { + t.Errorf("subteam.is_external should be false, was %v", e.Subteam.IsExternal) + } + if e.Subteam.DateCreate != 1624473600 { + t.Errorf("subteam.date_create should be 1624473600, was %d", e.Subteam.DateCreate) + } + if e.Subteam.DateUpdate != 1624473600 { + t.Errorf("subteam.date_update should be 1624473600, was %d", e.Subteam.DateUpdate) + } + if e.Subteam.DateDelete != 0 { + t.Errorf("subteam.date_delete should be 0, was %d", e.Subteam.DateDelete) + } + if e.Subteam.AutoType != "auto" { + t.Errorf("subteam.auto_type should be auto, was %s", e.Subteam.AutoType) + } + if e.Subteam.CreatedBy != "U1234567890" { + t.Errorf("subteam.created_by should be U1234567890, was %s", e.Subteam.CreatedBy) + } + if e.Subteam.UpdatedBy != "U1234567890" { + t.Errorf("subteam.updated_by should be U1234567890, was %s", e.Subteam.UpdatedBy) + } + if e.Subteam.DeletedBy != "" { + t.Errorf("subteam.deleted_by should be empty, was %s", e.Subteam.DeletedBy) + } + if len(e.Subteam.Prefs.Channels) != 1 || e.Subteam.Prefs.Channels[0] != "C1234567890" { + t.Errorf("subteam.prefs.channels should contain C1234567890, was %v", e.Subteam.Prefs.Channels) + } + if len(e.Subteam.Prefs.Groups) != 1 || e.Subteam.Prefs.Groups[0] != "G1234567890" { + t.Errorf("subteam.prefs.groups should contain G1234567890, was %v", e.Subteam.Prefs.Groups) + } + if len(e.Subteam.Users) != 1 || e.Subteam.Users[0] != "U1234567890" { + t.Errorf("subteam.users should contain U1234567890, was %v", e.Subteam.Users) + } + if e.Subteam.UserCount != 1 { + t.Errorf("subteam.user_count should be 1, was %d", e.Subteam.UserCount) + } +} + +func TestTeamDomainChangeEvent(t *testing.T) { + rawE := []byte(` + { + "type": "team_domain_change", + "url": "https://newdomain.slack.com", + "domain": "newdomain", + "team_id": "T1234" + } + `) + + var e TeamDomainChangeEvent + if err := json.Unmarshal(rawE, &e); err != nil { + t.Fatal(err) + } + if e.Type != "team_domain_change" { + t.Errorf("type should be team_domain_change, was %s", e.Type) + } + if e.URL != "https://newdomain.slack.com" { + t.Errorf("url should be https://newdomain.slack.com, was %s", e.URL) + } + if e.Domain != "newdomain" { + t.Errorf("domain should be newdomain, was %s", e.Domain) + } + if e.TeamID != "T1234" { + t.Errorf("team_id should be 'T1234', was %s", e.TeamID) + } +} + +func TestTeamRenameEvent(t *testing.T) { + rawE := []byte(` + { + "type": "team_rename", + "name": "new_team_name", + "team_id": "T1234" + } + `) + + var e TeamRenameEvent + if err := json.Unmarshal(rawE, &e); err != nil { + t.Fatal(err) + } + if e.Type != "team_rename" { + t.Errorf("type should be team_rename, was %s", e.Type) + } + if e.Name != "new_team_name" { + t.Errorf("name should be new_team_name, was %s", e.Name) + } + if e.TeamID != "T1234" { + t.Errorf("team_id should be 'T1234', was %s", e.TeamID) + } +} + +func TestUserChangeEvent(t *testing.T) { + jsonStr := `{ + "user": { + "id": "U1234567", + "team_id": "T1234567", + "name": "some-user", + "deleted": false, + "color": "4bbe2e", + "real_name": "Some User", + "tz": "America/Los_Angeles", + "tz_label": "Pacific Daylight Time", + "tz_offset": -25200, + "profile": { + "title": "", + "phone": "", + "skype": "", + "real_name": "Some User", + "real_name_normalized": "Some User", + "display_name": "", + "display_name_normalized": "", + "fields": {}, + "status_text": "riding a train", + "status_emoji": ":mountain_railway:", + "status_emoji_display_info": [], + "status_expiration": 0, + "avatar_hash": "g12345678910", + "first_name": "Some", + "last_name": "User", + "image_24": "https://secure.gravatar.com/avatar/cb0c2b2ca5e8de16be31a55a734d0f31.jpg?s=24&d=https%3A%2F%2Fdev.slack.com%2Fdev-cdn%2Fv1648136338%2Fimg%2Favatars%2Fuser_shapes%2Fava_0001-24.png", + "image_32": "https://secure.gravatar.com/avatar/cb0c2b2ca5e8de16be31a55a734d0f31.jpg?s=32&d=https%3A%2F%2Fdev.slack.com%2Fdev-cdn%2Fv1648136338%2Fimg%2Favatars%2Fuser_shapes%2Fava_0001-32.png", + "image_48": "https://secure.gravatar.com/avatar/cb0c2b2ca5e8de16be31a55a734d0f31.jpg?s=48&d=https%3A%2F%2Fdev.slack.com%2Fdev-cdn%2Fv1648136338%2Fimg%2Favatars%2Fuser_shapes%2Fava_0001-48.png", + "image_72": "https://secure.gravatar.com/avatar/cb0c2b2ca5e8de16be31a55a734d0f31.jpg?s=72&d=https%3A%2F%2Fdev.slack.com%2Fdev-cdn%2Fv1648136338%2Fimg%2Favatars%2Fuser_shapes%2Fava_0001-72.png", + "image_192": "https://secure.gravatar.com/avatar/cb0c2b2ca5e8de16be31a55a734d0f31.jpg?s=192&d=https%3A%2F%2Fdev.slack.com%2Fdev-cdn%2Fv1648136338%2Fimg%2Favatars%2Fuser_shapes%2Fava_0001-192.png", + "image_512": "https://secure.gravatar.com/avatar/cb0c2b2ca5e8de16be31a55a734d0f31.jpg?s=512&d=https%3A%2F%2Fdev.slack.com%2Fdev-cdn%2Fv1648136338%2Fimg%2Favatars%2Fuser_shapes%2Fava_0001-512.png", + "status_text_canonical": "", + "team": "T1234567" + }, + "is_admin": false, + "is_owner": false, + "is_primary_owner": false, + "is_restricted": false, + "is_ultra_restricted": false, + "is_bot": false, + "is_app_user": false, + "updated": 1648596421, + "is_email_confirmed": true, + "who_can_share_contact_card": "EVERYONE", + "locale": "en-US" + }, + "cache_ts": 1648596421, + "type": "user_change", + "event_ts": "1648596712.000001" + }` + + var event UserChangeEvent + if err := json.Unmarshal([]byte(jsonStr), &event); err != nil { + t.Errorf("Failed to unmarshal UserChangeEvent: %v", err) + } + + if event.Type != "user_change" { + t.Errorf("Expected type to be 'user_change', got %s", event.Type) + } + + if event.User.ID != "U1234567" { + t.Errorf("Expected user ID to be 'U1234567', got %s", event.User.ID) + } + + if event.User.Profile.StatusText != "riding a train" { + t.Errorf("Expected status text to be 'riding a train', got %s", event.User.Profile.StatusText) + } + + if event.User.Profile.StatusEmoji != ":mountain_railway:" { + t.Errorf("Expected status emoji to be ':mountain_railway:', got %s", event.User.Profile.StatusEmoji) + } + + if event.CacheTS != 1648596421 { + t.Errorf("Expected cache_ts to be 1648596421, got %d", event.CacheTS) + } + + if event.EventTS != "1648596712.000001" { + t.Errorf("Expected event_ts to be '1648596712.000001', got %s", event.EventTS) + } +} + +func TestAppDeletedEvent(t *testing.T) { + jsonStr := `{ + "type": "app_deleted", + "app_id": "A015CA1LGHG", + "app_name": "my-admin-app", + "app_owner_id": "U013B64J7MSZ", + "team_id": "E073D7H7BBE", + "team_domain": "ACME Enterprises", + "event_ts": "1700001891.279278" + }` + + var event AppDeletedEvent + if err := json.Unmarshal([]byte(jsonStr), &event); err != nil { + t.Errorf("Failed to unmarshal AppDeletedEvent: %v", err) + } + + if event.Type != "app_deleted" { + t.Errorf("Expected type to be 'app_deleted', got %s", event.Type) + } + + if event.AppName != "my-admin-app" { + t.Errorf("app_name should be 'my-admin-app', was %s", event.AppName) + } + + if event.AppOwnerID != "U013B64J7MSZ" { + t.Errorf("app_owner_id should be 'U013B64J7MSZ', was %s", event.AppOwnerID) + } + + if event.TeamID != "E073D7H7BBE" { + t.Errorf("team_id should be 'E073D7H7BBE', was %s", event.TeamID) + } +} + +func TestAppInstalledEvent(t *testing.T) { + jsonStr := `{ + "type": "app_installed", + "app_id": "A015CA1LGHG", + "app_name": "my-admin-app", + "app_owner_id": "U013B64J7MSZ", + "user_id": "U013B64J7SZ", + "team_id": "E073D7H7BBE", + "team_domain": "ACME Enterprises", + "event_ts": "1700001891.279278" + }` + + var event AppInstalledEvent + if err := json.Unmarshal([]byte(jsonStr), &event); err != nil { + t.Errorf("Failed to unmarshal AppInstalledEvent: %v", err) + } + + if event.Type != "app_installed" { + t.Errorf("Expected type to be 'app_installed', got %s", event.Type) + } + + if event.AppName != "my-admin-app" { + t.Errorf("app_name should be 'my-admin-app', was %s", event.AppName) + } + + if event.AppOwnerID != "U013B64J7MSZ" { + t.Errorf("app_owner_id should be 'U013B64J7MSZ', was %s", event.AppOwnerID) + } + + if event.TeamID != "E073D7H7BBE" { + t.Errorf("team_id should be 'E073D7H7BBE', was %s", event.TeamID) + } +} + +func TestAppRequestedEvent(t *testing.T) { + jsonStr := `{ + "type": "app_requested", + "app_request": { + "id": "1234", + "app": { + "id": "A5678", + "name": "Brent's app", + "description": "They're good apps, Bront.", + "help_url": "brontsapp.com", + "privacy_policy_url": "brontsapp.com", + "app_homepage_url": "brontsapp.com", + "app_directory_url": "https://slack.slack.com/apps/A102ARD7Y", + "is_app_directory_approved": true, + "is_internal": false, + "additional_info": "none" + }, + "previous_resolution": { + "status": "approved", + "scopes": [{ + "name": "app_requested", + "description": "allows this app to listen for app install requests", + "is_sensitive": false, + "token_type": "user" + }] + }, + "user": { + "id": "U1234", + "name": "Bront", + "email": "bront@brent.com" + }, + "team": { + "id": "T1234", + "name": "Brant App Team", + "domain": "brantappteam" + }, + "enterprise": null, + "scopes": [{ + "name": "app_requested", + "description": "allows this app to listen for app install requests", + "is_sensitive": false, + "token_type": "user" + }], + "message": "none" + } + }` + + var event AppRequestedEvent + if err := json.Unmarshal([]byte(jsonStr), &event); err != nil { + t.Errorf("Failed to unmarshal AppRequestedEvent: %v", err) + } + + if event.Type != "app_requested" { + t.Errorf("Expected type to be 'app_requested', got %s", event.Type) + } + + if event.AppRequest.ID != "1234" { + t.Errorf("app_request.id should be '1234', was %s", event.AppRequest.ID) + } + + if event.AppRequest.App.ID != "A5678" { + t.Fail() + } + + if event.AppRequest.User.ID != "U1234" { + t.Errorf("app_request.user.id should be 'U1234', was %s", event.AppRequest.User.ID) + } + + if event.AppRequest.Team.ID != "T1234" { + t.Fail() + } +} + +func TestAppUninstalledTeamEvent(t *testing.T) { + jsonStr := `{ + "type": "app_uninstalled_team", + "app_id": "A015CA1LGHG", + "app_name": "my-admin-app", + "app_owner_id": "U013B64J7MSZ", + "user_id": "U013B64J7SZ", + "team_id": "E073D7H7BBE", + "team_domain": "ACME Enterprises", + "event_ts": "1700001891.279278" + }` + + var event AppUninstalledTeamEvent + if err := json.Unmarshal([]byte(jsonStr), &event); err != nil { + t.Errorf("Failed to unmarshal AppUninstalledTeamEvent: %v", err) + } + + if event.Type != "app_uninstalled_team" { + t.Errorf("Expected type to be 'app_uninstalled_team', got %s", event.Type) + } + + if event.AppName != "my-admin-app" { + t.Errorf("app_name should be 'my-admin-app', was %s", event.AppName) + } + + if event.AppOwnerID != "U013B64J7MSZ" { + t.Errorf("app_owner_id should be 'U013B64J7MSZ', was %s", event.AppOwnerID) + } + + if event.TeamID != "E073D7H7BBE" { + t.Errorf("team_id should be 'E073D7H7BBE', was %s", event.TeamID) + } +} + +func TestCallRejectedEvent(t *testing.T) { + jsonStr := `{ + "token": "12345FVmRUzNDOAu12345h", + "team_id": "T123ABC456", + "api_app_id": "BBBU04BB4", + "event": { + "type": "call_rejected", + "call_id": "R123ABC456", + "user_id": "U123ABC456", + "channel_id": "D123ABC456", + "external_unique_id": "123-456-7890" + }, + "type": "event_callback", + "event_id": "Ev123ABC456", + "event_time": 1563448153, + "authed_users": ["U123ABC456"] + }` + + var event CallRejectedEvent + if err := json.Unmarshal([]byte(jsonStr), &event); err != nil { + t.Errorf("Failed to unmarshal CallRejectedEvent: %v", err) + } + + if event.Event.Type != "call_rejected" { + t.Errorf("Expected event type to be 'call_rejected', got %s", event.Event.Type) + } + if event.TeamID != "T123ABC456" { + t.Errorf("Expected team_id to be 'T123ABC456', got %s", event.TeamID) + } + if event.Event.CallID != "R123ABC456" { + t.Fail() + } + +} + +func TestChannelSharedEvent(t *testing.T) { + jsonStr := `{ + "type": "channel_shared", + "connected_team_id": "E163Q94DX", + "channel": "C123ABC456", + "event_ts": "1561064063.001100" + }` + + var event ChannelSharedEvent + if err := json.Unmarshal([]byte(jsonStr), &event); err != nil { + t.Errorf("Failed to unmarshal ChannelSharedEvent: %v", err) + } + + if event.Type != "channel_shared" { + t.Errorf("Expected type to be 'channel_shared', got %s", event.Type) + } + + if event.ConnectedTeamID != "E163Q94DX" { + t.Errorf("Expected connected_team_id to be 'E163Q94DX', got %s", event.ConnectedTeamID) + } + + if event.Channel != "C123ABC456" { + t.Fail() + } +} + +func TestFileCreatedEvent(t *testing.T) { + jsonStr := `{ + "type": "file_created", + "file_id": "F2147483862", + "file": { + "id": "F2147483862" + } + }` + + var event FileCreatedEvent + if err := json.Unmarshal([]byte(jsonStr), &event); err != nil { + t.Errorf("Failed to unmarshal FileCreatedEvent: %v", err) + } + + if event.Type != "file_created" { + t.Errorf("Expected type to be 'file_created', got %s", event.Type) + } + if event.FileID != "F2147483862" { + t.Errorf("Expected file_id to be 'F2147483862', got %s", event.FileID) + } +} + +func TestFilePublicEvent(t *testing.T) { + jsonStr := `{ + "type": "file_public", + "file_id": "F2147483862", + "file": { + "id": "F2147483862" + } + }` + + var event FilePublicEvent + if err := json.Unmarshal([]byte(jsonStr), &event); err != nil { + t.Errorf("Failed to unmarshal FilePublicEvent: %v", err) + } + + if event.Type != "file_public" { + t.Errorf("Expected type to be 'file_public', got %s", event.Type) + } + + if event.FileID != "F2147483862" { + t.Errorf("Expected file_id to be 'F2147483862', got %s", event.FileID) + } +} + +func TestFunctionExecutedEvent(t *testing.T) { + jsonStr := `{ + "type": "function_executed", + "function": { + "id": "Fn123456789O", + "callback_id": "sample_function", + "title": "Sample function", + "description": "Runs sample function", + "type": "app", + "input_parameters": [ + { + "type": "slack#/types/user_id", + "name": "user_id", + "description": "Message recipient", + "title": "User", + "is_required": true + } + ], + "output_parameters": [ + { + "type": "slack#/types/user_id", + "name": "user_id", + "description": "User that completed the function", + "title": "Greeting", + "is_required": true + } + ], + "app_id": "AP123456789", + "date_created": 1694727597, + "date_updated": 1698947481, + "date_deleted": 0 + }, + "inputs": { "user_id": "USER12345678" }, + "function_execution_id": "Fx1234567O9L", + "workflow_execution_id": "WxABC123DEF0", + "event_ts": "1698958075.998738", + "bot_access_token": "abcd-1325532282098-1322446258629-6123648410839-527a1cab3979cad288c9e20330d212cf" + }` + + var event FunctionExecutedEvent + if err := json.Unmarshal([]byte(jsonStr), &event); err != nil { + t.Errorf("Failed to unmarshal FunctionExecutedEvent: %v", err) + } + + if event.Type != "function_executed" { + t.Errorf("Expected type to be 'function_executed', got %s", event.Type) + } + + if event.Function.ID != "Fn123456789O" { + t.Errorf("Expected function.id to be 'Fn123456789O', got %s", event.Function.ID) + } + + if event.FunctionExecutionID != "Fx1234567O9L" { + t.Fail() + } +} + +func TestInviteRequestedEvent(t *testing.T) { + jsonStr := `{ + "type": "invite_requested", + "invite_request": { + "id": "12345", + "email": "bront@puppies.com", + "date_created": 123455, + "requester_ids": ["U123ABC456"], + "channel_ids": ["C123ABC456"], + "invite_type": "full_member", + "real_name": "Brent", + "date_expire": 123456, + "request_reason": "They're good dogs, Brant", + "team": { + "id": "T12345", + "name": "Puppy ratings workspace incorporated", + "domain": "puppiesrus" + } + } + }` + + var event InviteRequestedEvent + if err := json.Unmarshal([]byte(jsonStr), &event); err != nil { + t.Errorf("Failed to unmarshal InviteRequestedEvent: %v", err) + } + + if event.Type != "invite_requested" { + t.Errorf("Expected type to be 'invite_requested', got %s", event.Type) + } + + if event.InviteRequest.ID != "12345" { + t.Errorf("invite_request.id should be '12345', was %s", event.InviteRequest.ID) + } + + if event.InviteRequest.Email != "bront@puppies.com" { + t.Fail() + } +} + +func TestSharedChannelInviteRequested_UnmarshalJSON(t *testing.T) { + jsonData := ` + { + "actor": { + "id": "U012345ABCD", + "name": "primary-owner", + "is_bot": false, + "team_id": "E0123456ABC", + "timezone": "", + "real_name": "primary-owner", + "display_name": "" + }, + "channel_id": "C0123ABCDEF", + "event_type": "slack#/events/shared_channel_invite_requested", + "channel_name": "our-channel", + "channel_type": "public", + "target_users": [ + { + "email": "user@some-corp.com", + "invite_id": "I0123456ABC" + } + ], + "teams_in_channel": [ + { + "id": "E0123456ABC", + "icon": { + "image_34": "https://slack.com/some-corp/v123/img/abc_0123.png", + "image_default": true + }, + "name": "some_enterprise", + "domain": "someenterprise", + "is_verified": false, + "date_created": 1637947110, + "avatar_base_url": "https://slack.com/some-corp/", + "requires_sponsorship": false + }, + { + "id": "T012345ABCD", + "icon": { + "image_34": "https://slack.com/another-corp/v456/img/def_4567.png", + "image_default": true + }, + "name": "another_enterprise", + "domain": "anotherenterprise", + "is_verified": false, + "date_created": 1645550933, + "avatar_base_url": "https://slack.com/another-corp/", + "requires_sponsorship": false + } + ], + "is_external_limited": true, + "channel_date_created": 1718725442, + "channel_message_latest_counted_timestamp": 1718745614025449 + }` + + var event SharedChannelInviteRequestedEvent + err := json.Unmarshal([]byte(jsonData), &event) + if err != nil { + t.Fatalf("Failed to unmarshal JSON: %v", err) + } + + if event.Actor.ID != "U012345ABCD" { + t.Errorf("Expected Actor.ID to be 'U012345ABCD', got '%s'", event.Actor.ID) + } + if event.ChannelID != "C0123ABCDEF" { + t.Errorf("Expected ChannelID to be 'C0123ABCDEF', got '%s'", event.ChannelID) + } + if len(event.TargetUsers) != 1 || event.TargetUsers[0].Email != "user@some-corp.com" { + t.Errorf("Expected one TargetUser with Email 'user@some-corp.com', got '%v'", event.TargetUsers) + } + if len(event.TeamsInChannel) != 2 || event.TeamsInChannel[1].Name != "another_enterprise" { + t.Errorf("Expected second team to have name 'another_enterprise', got '%v'", event.TeamsInChannel) + } +}