Skip to content

Commit

Permalink
Merge remote-tracking branch 'upstream/master' into safer-socketmode
Browse files Browse the repository at this point in the history
Functionally revert #1170 as drafted approach takes correct path of
closing chan on goroutine producer side
  • Loading branch information
iaburton committed Apr 24, 2023
2 parents 377ffe4 + c4095cb commit 8c8b886
Show file tree
Hide file tree
Showing 17 changed files with 219 additions and 30 deletions.
25 changes: 25 additions & 0 deletions .github/workflows/stale.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
name: 'Close stale issues and PRs'
on:
schedule:
- cron: '0 0 * * 1' # every Monday 0:00 UTC

workflow_dispatch:

permissions:
issues: write
pull-requests: write

jobs:
stale:
runs-on: ubuntu-latest
steps:
- uses: actions/stale@1160a2240286f5da8ec72b1c0816ce2481aabf84 # v8.0.0
with:
any-of-labels: 'feedback given'
days-before-stale: 45
days-before-pr-close: 10
stale-issue-message: 'This issue is stale because it has been open 45 days with no activity. Remove stale label or comment or this will be closed in 10 days.'
stale-pr-message: 'This PR is stale because it has been open 45 days with no activity. Remove stale label or comment or this will be closed in 10 days.'
close-issue-message: 'This issue was closed because it has been stalled for 10 days with no activity.'
close-pr-message: 'This PR was closed because it has been stalled for 10 days with no activity.'
operations-per-run: 120
12 changes: 9 additions & 3 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@ jobs:
strategy:
matrix:
go:
- '1.17'
- '1.18'
- '1.19'
- '1.20'
name: test go-${{ matrix.go }}
steps:
- uses: actions/checkout@v3
Expand All @@ -29,8 +29,14 @@ jobs:
runs-on: ubuntu-22.04
name: lint
steps:
- uses: actions/setup-go@v4
with:
go-version: '1.20'
cache: false
- uses: actions/checkout@v3
with:
fetch-depth: 0
- name: golangci-lint
uses: golangci/golangci-lint-action@537aa1903e5d359d0b27dbc19ddd22c5087f3fbc # v3.2.0
uses: golangci/golangci-lint-action@08e2f20817b15149a52b5b3ebe7de50aff2ba8c5 # v3.4.0
with:
version: v1.48.0
version: v1.52.2
1 change: 1 addition & 0 deletions block.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ type BlockAction struct {
SelectedConversations []string `json:"selected_conversations"`
SelectedDate string `json:"selected_date"`
SelectedTime string `json:"selected_time"`
SelectedDateTime int64 `json:"selected_date_time"`
InitialOption OptionBlockObject `json:"initial_option"`
InitialUser string `json:"initial_user"`
InitialChannel string `json:"initial_channel"`
Expand Down
5 changes: 5 additions & 0 deletions block_conv.go
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,8 @@ func (b *InputBlock) UnmarshalJSON(data []byte) error {
e = &DatePickerBlockElement{}
case "timepicker":
e = &TimePickerBlockElement{}
case "datetimepicker":
e = &DateTimePickerBlockElement{}
case "plain_text_input":
e = &PlainTextInputBlockElement{}
case "email_text_input":
Expand Down Expand Up @@ -190,6 +192,8 @@ func (b *BlockElements) UnmarshalJSON(data []byte) error {
blockElement = &DatePickerBlockElement{}
case "timepicker":
blockElement = &TimePickerBlockElement{}
case "datetimepicker":
blockElement = &DateTimePickerBlockElement{}
case "plain_text_input":
blockElement = &PlainTextInputBlockElement{}
case "email_text_input":
Expand Down Expand Up @@ -233,6 +237,7 @@ func (a *Accessory) MarshalJSON() ([]byte, error) {

// UnmarshalJSON implements the Unmarshaller interface for Accessory, so that any JSON
// unmarshalling is delegated and proper type determination can be made before unmarshal
// Note: datetimepicker is not supported in Accessory
func (a *Accessory) UnmarshalJSON(data []byte) error {
var r json.RawMessage

Expand Down
24 changes: 24 additions & 0 deletions block_element.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ const (
METOverflow MessageElementType = "overflow"
METDatepicker MessageElementType = "datepicker"
METTimepicker MessageElementType = "timepicker"
METDatetimepicker MessageElementType = "datetimepicker"
METPlainTextInput MessageElementType = "plain_text_input"
METRadioButtons MessageElementType = "radio_buttons"
METEmailTextInput MessageElementType = "email_text_input"
Expand Down Expand Up @@ -392,6 +393,29 @@ func NewTimePickerBlockElement(actionID string) *TimePickerBlockElement {
}
}

// DateTimePickerBlockElement defines an element that allows the selection of both
// a date and a time of day formatted as a UNIX timestamp.
// More Information: https://api.slack.com/reference/messaging/block-elements#datetimepicker
type DateTimePickerBlockElement struct {
Type MessageElementType `json:"type"`
ActionID string `json:"action_id,omitempty"`
InitialDateTime int64 `json:"initial_date_time,omitempty"`
Confirm *ConfirmationBlockObject `json:"confirm,omitempty"`
}

// ElementType returns the type of the Element
func (s DateTimePickerBlockElement) ElementType() MessageElementType {
return s.Type
}

// NewDatePickerBlockElement returns an instance of a datetime picker element
func NewDateTimePickerBlockElement(actionID string) *DateTimePickerBlockElement {
return &DateTimePickerBlockElement{
Type: METDatetimepicker,
ActionID: actionID,
}
}

// EmailTextInputBlockElement creates a field where a user can enter email
// data.
// email-text-input elements are currently only available in modals.
Expand Down
6 changes: 6 additions & 0 deletions block_element_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,12 @@ func TestNewTimePickerBlockElement(t *testing.T) {
assert.Equal(t, timepickerElement.ActionID, "test")
}

func TestNewDateTimePickerBlockElement(t *testing.T) {
datetimepickerElement := NewDateTimePickerBlockElement("test")
assert.Equal(t, string(datetimepickerElement.Type), "datetimepicker")
assert.Equal(t, datetimepickerElement.ActionID, "test")
}

func TestNewPlainTextInputBlockElement(t *testing.T) {

plainTextInputElement := NewPlainTextInputBlockElement(nil, "test")
Expand Down
2 changes: 1 addition & 1 deletion block_rich_text.go
Original file line number Diff line number Diff line change
Expand Up @@ -294,7 +294,7 @@ func NewRichTextSectionLinkElement(url, text string, style *RichTextSectionTextS
type RichTextSectionTeamElement struct {
Type RichTextSectionElementType `json:"type"`
TeamID string `json:"team_id"`
Style *RichTextSectionTextStyle `json:"style.omitempty"`
Style *RichTextSectionTextStyle `json:"style,omitempty"`
}

func (r RichTextSectionTeamElement) RichTextSectionElementType() RichTextSectionElementType {
Expand Down
4 changes: 1 addition & 3 deletions examples/pins/pins.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,7 @@ import (
"github.com/slack-go/slack"
)

/*
WARNING: This example is destructive in the sense that it create a channel called testpinning
*/
// WARNING: This example is destructive in the sense that it create a channel called testpinning
func main() {
var (
apiToken string
Expand Down
5 changes: 3 additions & 2 deletions examples/socketmode/socketmode.go
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ func main() {
innerEvent := eventsAPIEvent.InnerEvent
switch ev := innerEvent.Data.(type) {
case *slackevents.AppMentionEvent:
_, _, err := api.PostMessage(ev.Channel, slack.MsgOptionText("Yes, hello.", false))
_, _, err := client.PostMessage(ev.Channel, slack.MsgOptionText("Yes, hello.", false))
if err != nil {
fmt.Printf("failed posting message: %v", err)
}
Expand Down Expand Up @@ -137,7 +137,8 @@ func main() {
),
),
),
}}
},
}

client.Ack(*evt.Request, payload)
default:
Expand Down
9 changes: 5 additions & 4 deletions messages.go
Original file line number Diff line number Diff line change
Expand Up @@ -100,10 +100,11 @@ type Msg struct {
Members []string `json:"members,omitempty"`

// channels.replies, groups.replies, im.replies, mpim.replies
ReplyCount int `json:"reply_count,omitempty"`
Replies []Reply `json:"replies,omitempty"`
ParentUserId string `json:"parent_user_id,omitempty"`
LatestReply string `json:"latest_reply,omitempty"`
ReplyCount int `json:"reply_count,omitempty"`
ReplyUsers []string `json:"reply_users,omitempty"`
Replies []Reply `json:"replies,omitempty"`
ParentUserId string `json:"parent_user_id,omitempty"`
LatestReply string `json:"latest_reply,omitempty"`

// file_share, file_comment, file_mention
Files []File `json:"files,omitempty"`
Expand Down
25 changes: 18 additions & 7 deletions slackevents/inner_events.go
Original file line number Diff line number Diff line change
Expand Up @@ -536,6 +536,14 @@ type TeamAccessRevokedEvent struct {
TeamIDs []string `json:"team_ids"`
}

// UserProfileChangedEvent is sent if access to teams was revoked for your org-wide app.
type UserProfileChangedEvent struct {
User *slack.User `json:"user"`
CacheTs int `json:"cache_ts"`
Type string `json:"type"`
EventTs string `json:"event_ts"`
}

type EventsAPIType string

const (
Expand Down Expand Up @@ -585,9 +593,9 @@ const (
LinkShared = EventsAPIType("link_shared")
// Message A message was posted to a channel, private channel (group), im, or mim
Message = EventsAPIType("message")
// Member Joined Channel
// MemberJoinedChannel is sent if a member joined a channel.
MemberJoinedChannel = EventsAPIType("member_joined_channel")
// Member Left Channel
// MemberLeftChannel is sent if a member left a channel.
MemberLeftChannel = EventsAPIType("member_left_channel")
// PinAdded An item was pinned to a channel
PinAdded = EventsAPIType("pin_added")
Expand All @@ -607,14 +615,16 @@ const (
WorkflowStepExecute = EventsAPIType("workflow_step_execute")
// MessageMetadataPosted A message with metadata was posted
MessageMetadataPosted = EventsAPIType("message_metadata_posted")
// MessageMetadataPosted A message with metadata was updated
// MessageMetadataUpdated A message with metadata was updated
MessageMetadataUpdated = EventsAPIType("message_metadata_updated")
// MessageMetadataPosted A message with metadata was deleted
// MessageMetadataDeleted A message with metadata was deleted
MessageMetadataDeleted = EventsAPIType("message_metadata_deleted")
// TeamAccessGranted is sent if access to teams was granted for your org-wide app.
TeamAccessGranted = EventsAPIType("team_access_granted")
// TeamAccessrevoked is sent if access to teams was revoked for your org-wide app.
TeamAccessrevoked = EventsAPIType("team_access_revoked")
// TeamAccessRevoked is sent if access to teams was revoked for your org-wide app.
TeamAccessRevoked = EventsAPIType("team_access_revoked")
// UserProfileChanged is sent if a user's profile information has changed.
UserProfileChanged = EventsAPIType("user_profile_changed")
)

// EventsAPIInnerEventMapping maps INNER Event API events to their corresponding struct
Expand Down Expand Up @@ -658,5 +668,6 @@ var EventsAPIInnerEventMapping = map[EventsAPIType]interface{}{
MessageMetadataUpdated: MessageMetadataUpdatedEvent{},
MessageMetadataDeleted: MessageMetadataDeletedEvent{},
TeamAccessGranted: TeamAccessGrantedEvent{},
TeamAccessrevoked: TeamAccessRevokedEvent{},
TeamAccessRevoked: TeamAccessRevokedEvent{},
UserProfileChanged: UserProfileChangedEvent{},
}
93 changes: 93 additions & 0 deletions slackevents/inner_events_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -821,3 +821,96 @@ func TestMessageMetadataDeleted(t *testing.T) {
t.Fail()
}
}

func TestUserProfileChanged(t *testing.T) {
rawE := []byte(`
{
"token": "whatever",
"team_id": "whatever",
"api_app_id": "whatever",
"event": {
"user": {
"id": "whatever",
"team_id": "whatever",
"name": "whatever",
"deleted": true,
"profile": {
"title": "",
"phone": "",
"skype": "",
"real_name": "whatever",
"real_name_normalized": "whatever",
"display_name": "",
"display_name_normalized": "",
"fields": {},
"status_text": "",
"status_emoji": "",
"status_emoji_display_info": [],
"status_expiration": 0,
"avatar_hash": "whatever",
"api_app_id": "whatever",
"always_active": true,
"bot_id": "whatever",
"first_name": "whatever",
"last_name": "",
"image_24": "https://secure.gravatar.com/avatar/whatever.jpg",
"image_32": "https://secure.gravatar.com/avatar/whatever.jpg",
"image_48": "https://secure.gravatar.com/avatar/whatever.jpg",
"image_72": "https://secure.gravatar.com/avatar/whatever.jpg",
"image_192": "https://secure.gravatar.com/avatar/whatever.jpg",
"image_512": "https://secure.gravatar.com/avatar/whatever.jpg",
"status_text_canonical": "",
"team": "whatever"
},
"is_bot": true,
"is_app_user": false,
"updated": 1678984254
},
"cache_ts": 1678984254,
"type": "user_profile_changed",
"event_ts": "1678984255.006500"
},
"type": "event_callback",
"event_id": "whatever",
"event_time": 1678984255,
"authorizations": [
{
"enterprise_id": null,
"team_id": "whatever",
"user_id": "whatever",
"is_bot": false,
"is_enterprise_install": false
}
],
"is_ext_shared_channel": false
}
`)

evt := &EventsAPICallbackEvent{}
err := json.Unmarshal(rawE, &evt)
if err != nil {
t.Error(err)
}

if evt.Type != "event_callback" {
t.Fail()
}

parsedEvent, err := parseInnerEvent(evt)
if err != nil {
t.Error(err)
}

if parsedEvent.InnerEvent.Type != "user_profile_changed" {
t.Fail()
}

actual, ok := parsedEvent.InnerEvent.Data.(*UserProfileChangedEvent)
if !ok {
t.Fail()
}

if actual.User.Name != "whatever" {
t.Fail()
}
}
6 changes: 4 additions & 2 deletions slacktest/README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
# slacktest

This package was copied from https://github.com/lusis/slack-test for historical reasons.
This package's license is the following.
This package was originally copied from https://github.com/lusis/slack-test for historical reasons.
It is currently in use with some modifications.

The license of this package is as follows.

---

Expand Down
4 changes: 2 additions & 2 deletions slacktest/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,10 @@ type Customize interface {
Handle(pattern string, handler http.HandlerFunc)
}

type binder func(Customize)
type Binder func(Customize)

// NewTestServer returns a slacktest.Server ready to be started
func NewTestServer(custom ...binder) *Server {
func NewTestServer(custom ...Binder) *Server {
serverChans := newMessageChannels()

channels := &serverChannels{}
Expand Down
2 changes: 0 additions & 2 deletions socketmode/socket_mode_managed_conn.go
Original file line number Diff line number Diff line change
Expand Up @@ -121,8 +121,6 @@ func (smc *Client) run(ctx context.Context, connectionCount int) error {
}
}()

// We don't wait on runMessageReceiver because it doesn't block on a select with the context,
// so we'd have to wait for the ReadJSON to time out, which can take a while.
go func() {
defer cancel()
// We close messages here as it is the producer for the channel.
Expand Down
Loading

0 comments on commit 8c8b886

Please sign in to comment.