diff --git a/app/internal/domain/repository/slack.go b/app/internal/domain/repository/slack.go index 466f61e..67715fe 100644 --- a/app/internal/domain/repository/slack.go +++ b/app/internal/domain/repository/slack.go @@ -24,8 +24,15 @@ import ( ) type SlackRepository interface { + // PostMessage send a message to a channel PostMessage(ctx context.Context, channelID, message, ts string) error + + // PostEphemeral sends an ephemeral message to user in a channel PostEphemeral(ctx context.Context, channelID, message, ts, userID string) error + + // GetParentMessage gets Slack message that started the thread GetParentMessage(ctx context.Context, channelID, ts string) (*model.SlackMessage, error) + + // ListUsersEmail fetches users email ListUsersEmail(ctx context.Context, userID []string) ([]*model.SlackUserEmail, error) } diff --git a/app/internal/domain/service/slack_reaction_users.go b/app/internal/domain/service/slack_reaction_users.go index cab602d..c0a835f 100644 --- a/app/internal/domain/service/slack_reaction_users.go +++ b/app/internal/domain/service/slack_reaction_users.go @@ -68,18 +68,19 @@ func (s *slackReactionUsersService) ListUsersEmailByReaction(ctx context.Context if err != nil { return nil, err } - inviteUserIDs := s.getReactionUserIDs(ctx, msg.Reactions, reactionName) - inviteUserEmails, err := s.chunkedListUsersEmail(ctx, inviteUserIDs) + reactedUserIDs := s.getReactionUserIDs(ctx, msg.Reactions, reactionName) + reactedUserEmails, err := s.chunkedListUsersEmail(ctx, reactedUserIDs) if err != nil { return nil, err } - return inviteUserEmails, nil + return reactedUserEmails, nil } // getReactionUserIDs get reaction users by reactionName func (s *slackReactionUsersService) getReactionUserIDs(ctx context.Context, reactions []*model.SlackReaction, reactionName string) []string { var userIDs []string var targetReactions []*model.SlackReaction + // filtered reactions by reactionName for _, reaction := range reactions { rn := slack.ExtractReactionName(reaction.Name) if slack.RemoveSkinToneFromReaction(rn) == reactionName { diff --git a/app/internal/domain/service/slack_reaction_users_test.go b/app/internal/domain/service/slack_reaction_users_test.go index 28a4b66..dbbcbf5 100644 --- a/app/internal/domain/service/slack_reaction_users_test.go +++ b/app/internal/domain/service/slack_reaction_users_test.go @@ -41,10 +41,12 @@ func Test_slackReactionUsersService_ListUsersEmailByReaction(t *testing.T) { { Name: "join", UserIDs: []string{"user01", "user02"}, + Count: 2, }, { Name: "reactionSample", UserIDs: []string{"user02", "user03"}, + Count: 2, }, }, } diff --git a/app/internal/model/slack_message.go b/app/internal/model/slack_message.go index f4a4f2c..aef9993 100644 --- a/app/internal/model/slack_message.go +++ b/app/internal/model/slack_message.go @@ -23,6 +23,7 @@ type SlackMessage struct { type SlackReaction struct { Name string + Count int UserIDs []string } diff --git a/app/internal/repository/slack.go b/app/internal/repository/slack.go index dc44f6b..7d0545a 100644 --- a/app/internal/repository/slack.go +++ b/app/internal/repository/slack.go @@ -18,9 +18,10 @@ package repository import ( "context" - "fmt" - "github.com/moneyforward/auriga/app/pkg/slack" + "github.com/slack-go/slack" + + pkgslack "github.com/moneyforward/auriga/app/pkg/slack" "github.com/moneyforward/auriga/app/internal/model" @@ -28,10 +29,10 @@ import ( ) type slackRepository struct { - client slack.Client + client pkgslack.Client } -func newSlackRepository(client slack.Client) *slackRepository { +func newSlackRepository(client pkgslack.Client) *slackRepository { return &slackRepository{ client: client, } @@ -49,35 +50,52 @@ func (r *slackRepository) PostEphemeral(ctx context.Context, channelID, message, func (r *slackRepository) GetParentMessage(ctx context.Context, channelID, ts string) (*model.SlackMessage, error) { msgs, err := r.client.GetConversationReplies(ctx, channelID, ts) if err != nil { - if errors.Is(err, slack.ErrThreadNotFound) { + if errors.Is(err, pkgslack.ErrThreadNotFound) { return nil, errThreadNotfound } else { return nil, err } } + if len(msgs) <= 0 { + return nil, errors.New("number of messages is zero") + } + parentMessage := msgs[0] + if r.isIncompleteReaction(parentMessage.Reactions) { + // get full reactions + parentMessage.Reactions, err = r.client.GetReaction(ctx, channelID, ts, true) + if err != nil { + return nil, err + } + } + var reactions []*model.SlackReaction + for _, reaction := range parentMessage.Reactions { + reactions = append(reactions, &model.SlackReaction{ + Name: reaction.Name, + UserIDs: reaction.Users, + Count: reaction.Count, + }) + } + return &model.SlackMessage{ + ChannelID: parentMessage.Channel, + Reactions: reactions, + }, nil +} - if len(msgs) > 0 { - fmt.Printf("%#v \n", msgs[0]) - parentMessage := msgs[0] - var reactions []*model.SlackReaction - for _, reaction := range parentMessage.Reactions { - reactions = append(reactions, &model.SlackReaction{ - Name: reaction.Name, - UserIDs: reaction.Users, - }) +// isIncompleteReaction returns true if more fetches is required +// reactions[*].Count may be greater than len(reactions[*].Users), at which point a fetch is required. +func (r *slackRepository) isIncompleteReaction(reactions []slack.ItemReaction) bool { + for _, reaction := range reactions { + if reaction.Count > len(reaction.Users) { + return true } - return &model.SlackMessage{ - ChannelID: parentMessage.Channel, - Reactions: reactions, - }, nil } - return nil, errors.New("number of messages is zero") + return false } func (r *slackRepository) ListUsersEmail(ctx context.Context, userID []string) ([]*model.SlackUserEmail, error) { users, err := r.client.GetUsersInfo(ctx, userID...) if err != nil { - if errors.Is(err, slack.ErrUserNotFound) { + if errors.Is(err, pkgslack.ErrUserNotFound) { return nil, errUserNotFound } else { return nil, err diff --git a/app/pkg/slack/client.go b/app/pkg/slack/client.go index 18eddad..1a484ac 100644 --- a/app/pkg/slack/client.go +++ b/app/pkg/slack/client.go @@ -28,6 +28,7 @@ type Client interface { PostEphemeral(ctx context.Context, channelID, userID, ts, message string) error GetConversationReplies(ctx context.Context, channelID, ts string) ([]slack.Message, error) GetUsersInfo(ctx context.Context, userID ...string) (*[]slack.User, error) + GetReaction(ctx context.Context, channelID, ts string, full bool) ([]slack.ItemReaction, error) GetClient() *slack.Client GetAppUserID() string @@ -118,6 +119,15 @@ func (c *client) GetUsersInfo(ctx context.Context, userID ...string) (*[]slack.U return users, nil } +func (c *client) GetReaction(ctx context.Context, channelID, ts string, full bool) ([]slack.ItemReaction, error) { + return c.Client.GetReactionsContext(ctx, slack.ItemRef{ + Channel: channelID, + Timestamp: ts, + }, slack.GetReactionsParameters{ + Full: full, + }) +} + func (c *client) GetClient() *slack.Client { return c.Client }