Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[GH-512,513] Fixed issue #512 and #513 on github plugin 'Updated subscription success messages' #661

Merged
merged 11 commits into from
Nov 28, 2023
Merged
147 changes: 130 additions & 17 deletions server/plugin/command.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,20 @@ var validFeatures = map[string]bool{
featureStars: true,
}

type Features string

func (features Features) String() string {
return string(features)
}

func (features Features) FormattedString() string {
return "`" + strings.Join(strings.Split(features.String(), ","), "`, `") + "`"
}

func (features Features) ToSlice() []string {
return strings.Split(string(features), ",")
}

// validateFeatures returns false when 1 or more given features
// are invalid along with a list of the invalid features.
func validateFeatures(features []string) (bool, []string) {
Expand Down Expand Up @@ -264,7 +278,7 @@ func (p *Plugin) handleSubscriptionsList(_ *plugin.Context, args *model.CommandA
}
for _, sub := range subs {
subFlags := sub.Flags.String()
txt += fmt.Sprintf("* `%s` - %s", strings.Trim(sub.Repository, "/"), sub.Features)
txt += fmt.Sprintf("* `%s` - %s", strings.Trim(sub.Repository, "/"), sub.Features.String())
if subFlags != "" {
txt += fmt.Sprintf(" %s", subFlags)
}
Expand All @@ -274,16 +288,30 @@ func (p *Plugin) handleSubscriptionsList(_ *plugin.Context, args *model.CommandA
return txt
}

func (p *Plugin) createPost(channelID, userID, message string) error {
post := &model.Post{
ChannelId: channelID,
UserId: userID,
Message: message,
}

if _, appErr := p.API.CreatePost(post); appErr != nil {
p.API.LogWarn("Error while creating post", "Post", post, "Error", appErr.Error())
return appErr
}

return nil
}

func (p *Plugin) handleSubscribesAdd(_ *plugin.Context, args *model.CommandArgs, parameters []string, userInfo *GitHubUserInfo) string {
subscriptionEvents := Features("pulls,issues,creates,deletes")
if len(parameters) == 0 {
return "Please specify a repository."
}

config := p.getConfiguration()
baseURL := config.getBaseURL()

features := "pulls,issues,creates,deletes"
flags := SubscriptionFlags{}

if len(parameters) > 1 {
flagParams := parameters[1:]

Expand All @@ -300,15 +328,15 @@ func (p *Plugin) handleSubscribesAdd(_ *plugin.Context, args *model.CommandArgs,
parsedFlag := parseFlag(flag)

if parsedFlag == flagFeatures {
features = value
subscriptionEvents = Features(value)
continue
}
if err := flags.AddFlag(parsedFlag, value); err != nil {
return fmt.Sprintf("Unsupported value for flag %s", flag)
}
}

fs := strings.Split(features, ",")
fs := subscriptionEvents.ToSlice()
if SliceContainsString(fs, featureIssues) && SliceContainsString(fs, featureIssueCreation) {
return "Feature list cannot contain both issue and issue_creations"
}
Expand All @@ -327,22 +355,49 @@ func (p *Plugin) handleSubscribesAdd(_ *plugin.Context, args *model.CommandArgs,

ctx := context.Background()
githubClient := p.githubConnectUser(ctx, userInfo)
user, appErr := p.API.GetUser(args.UserId)
if appErr != nil {
return errors.Wrap(appErr, "failed to get the user").Error()
}

owner, repo := parseOwnerAndRepo(parameters[0], baseURL)
previousSubscribedEvents, err := p.getSubscribedFeatures(args.ChannelId, owner, repo)
if err != nil {
return errors.Wrap(err, "failed to get the subscribed events").Error()
}

var previousSubscribedEventMessage string
if previousSubscribedEvents != "" {
previousSubscribedEventMessage = fmt.Sprintf("\nThe previous subscription with: %s was overwritten.\n", previousSubscribedEvents.FormattedString())
}

owner, repo := parseOwnerAndRepo(parameters[0], config.getBaseURL())
if repo == "" {
if err := p.SubscribeOrg(ctx, githubClient, args.UserId, owner, args.ChannelId, features, flags); err != nil {
return err.Error()
if err = p.SubscribeOrg(ctx, githubClient, args.UserId, owner, args.ChannelId, subscriptionEvents, flags); err != nil {
return errors.Wrap(err, "failed to get the subscribed org").Error()
}
orgLink := baseURL + owner
subscriptionSuccess := fmt.Sprintf("@%v subscribed this channel to [%s](%s) with the following events: %s.", user.Username, owner, orgLink, subscriptionEvents.FormattedString())

return fmt.Sprintf("Successfully subscribed to organization %s.", owner)
if previousSubscribedEvents != "" {
subscriptionSuccess += previousSubscribedEventMessage
}

if err = p.createPost(args.ChannelId, p.BotUserID, subscriptionSuccess); err != nil {
return fmt.Sprintf("%s error creating the public post: %s", subscriptionSuccess, err.Error())
}

return ""
}

if err := p.Subscribe(ctx, githubClient, args.UserId, owner, repo, args.ChannelId, features, flags); err != nil {
return err.Error()
if err = p.Subscribe(ctx, githubClient, args.UserId, owner, repo, args.ChannelId, subscriptionEvents, flags); err != nil {
return errors.Wrap(err, "failed to create a subscription").Error()
}
repoLink := config.getBaseURL() + owner + "/" + repo

msg := fmt.Sprintf("Successfully subscribed to [%s](%s).", repo, repoLink)
msg := fmt.Sprintf("@%v subscribed this channel to [%s/%s](%s) with the following events: %s", user.Username, owner, repo, repoLink, subscriptionEvents.FormattedString())
if previousSubscribedEvents != "" {
msg += previousSubscribedEventMessage
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we add a space between the two concatenated strings? Same for other concatenations here in this function

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@mickmister This is how it looks
Screenshot from 2023-03-28 10-38-43
Screenshot from 2023-03-28 10-39-00

}

ghRepo, _, err := githubClient.Repositories.Get(ctx, owner, repo)
if err != nil {
Expand All @@ -351,22 +406,80 @@ func (p *Plugin) handleSubscribesAdd(_ *plugin.Context, args *model.CommandArgs,
msg += "\n\n**Warning:** You subscribed to a private repository. Anyone with access to this channel will be able to read the events getting posted here."
}

return msg
if err = p.createPost(args.ChannelId, p.BotUserID, msg); err != nil {
return fmt.Sprintf("%s\nError creating the public post: %s", msg, appErr.Error())
}

return ""
Kshitij-Katiyar marked this conversation as resolved.
Show resolved Hide resolved
}

func (p *Plugin) getSubscribedFeatures(channelID, owner, repo string) (Features, error) {
var previousFeatures Features
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is this named previousFeatures?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These are Features or events of an subscription which are going to be overwritten due to creation of new subscription.

subs, err := p.GetSubscriptionsByChannel(channelID)
if err != nil {
return previousFeatures, err
}

for _, sub := range subs {
fullRepoName := repo
if owner != "" {
fullRepoName = owner + "/" + repo
}

if sub.Repository == fullRepoName {
previousFeatures = sub.Features
return previousFeatures, nil
}
}

return previousFeatures, nil
}
func (p *Plugin) handleUnsubscribe(_ *plugin.Context, args *model.CommandArgs, parameters []string, _ *GitHubUserInfo) string {
if len(parameters) == 0 {
return "Please specify a repository."
}

repo := parameters[0]
config := p.getConfiguration()
owner, repo := parseOwnerAndRepo(repo, config.getBaseURL())
if owner == "" && repo == "" {
return "invalid repository"
}

if err := p.Unsubscribe(args.ChannelId, repo); err != nil {
p.client.Log.Warn("Failed to unsubscribe", "repo", repo, "error", err.Error())
owner = strings.ToLower(owner)
repo = strings.ToLower(repo)
if err := p.Unsubscribe(args.ChannelId, repo, owner); err != nil {
p.API.LogWarn("Failed to unsubscribe", "repo", repo, "error", err.Error())
return "Encountered an error trying to unsubscribe. Please try again."
}

return fmt.Sprintf("Successfully unsubscribed from %s.", repo)
baseURL := config.getBaseURL()
user, appErr := p.API.GetUser(args.UserId)
if appErr != nil {
p.API.LogWarn("Error while fetching user details", "Error", appErr.Error())
return fmt.Sprintf("error while fetching user details: %s", appErr.Error())
}

unsubscribeMessage := ""
if repo == "" {
orgLink := baseURL + owner
unsubscribeMessage = fmt.Sprintf("@%v unsubscribed this channel from [%s](%s)", user.Username, owner, orgLink)

if err := p.createPost(args.ChannelId, p.BotUserID, unsubscribeMessage); err != nil {
return fmt.Sprintf("%s error creating the public post: %s", unsubscribeMessage, err.Error())
}

return ""
}

repoLink := baseURL + owner + "/" + repo
unsubscribeMessage = fmt.Sprintf("@%v unsubscribed this channel from [%s/%s](%s)", user.Username, owner, repo, repoLink)

if err := p.createPost(args.ChannelId, p.BotUserID, unsubscribeMessage); err != nil {
return fmt.Sprintf("%s error creating the public post: %s", unsubscribeMessage, err.Error())
}

return ""
}

func (p *Plugin) handleDisconnect(_ *plugin.Context, args *model.CommandArgs, _ []string, _ *GitHubUserInfo) string {
Expand Down
42 changes: 16 additions & 26 deletions server/plugin/subscriptions.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ func (s SubscriptionFlags) String() string {
type Subscription struct {
ChannelID string
CreatorID string
Features string
Features Features
Flags SubscriptionFlags
Repository string
}
Expand All @@ -67,51 +67,51 @@ type Subscriptions struct {
}

func (s *Subscription) Pulls() bool {
return strings.Contains(s.Features, featurePulls)
return strings.Contains(s.Features.String(), featurePulls)
}

func (s *Subscription) PullsMerged() bool {
return strings.Contains(s.Features, "pulls_merged")
return strings.Contains(s.Features.String(), "pulls_merged")
}

func (s *Subscription) IssueCreations() bool {
return strings.Contains(s.Features, "issue_creations")
return strings.Contains(s.Features.String(), "issue_creations")
}

func (s *Subscription) Issues() bool {
return strings.Contains(s.Features, featureIssues)
return strings.Contains(s.Features.String(), featureIssues)
}

func (s *Subscription) Pushes() bool {
return strings.Contains(s.Features, "pushes")
return strings.Contains(s.Features.String(), "pushes")
}

func (s *Subscription) Creates() bool {
return strings.Contains(s.Features, "creates")
return strings.Contains(s.Features.String(), "creates")
}

func (s *Subscription) Deletes() bool {
return strings.Contains(s.Features, "deletes")
return strings.Contains(s.Features.String(), "deletes")
}

func (s *Subscription) IssueComments() bool {
return strings.Contains(s.Features, "issue_comments")
return strings.Contains(s.Features.String(), "issue_comments")
}

func (s *Subscription) PullReviews() bool {
return strings.Contains(s.Features, "pull_reviews")
return strings.Contains(s.Features.String(), "pull_reviews")
}

func (s *Subscription) Stars() bool {
return strings.Contains(s.Features, featureStars)
return strings.Contains(s.Features.String(), featureStars)
}

func (s *Subscription) Label() string {
if !strings.Contains(s.Features, "label:") {
if !strings.Contains(s.Features.String(), "label:") {
return ""
}

labelSplit := strings.Split(s.Features, "\"")
labelSplit := strings.Split(s.Features.String(), "\"")
if len(labelSplit) < 3 {
return ""
}
Expand All @@ -127,7 +127,7 @@ func (s *Subscription) RenderStyle() string {
return s.Flags.RenderStyle
}

func (p *Plugin) Subscribe(ctx context.Context, githubClient *github.Client, userID, owner, repo, channelID, features string, flags SubscriptionFlags) error {
func (p *Plugin) Subscribe(ctx context.Context, githubClient *github.Client, userID, owner, repo, channelID string, features Features, flags SubscriptionFlags) error {
if owner == "" {
return errors.Errorf("invalid repository")
}
Expand Down Expand Up @@ -184,7 +184,7 @@ func (p *Plugin) Subscribe(ctx context.Context, githubClient *github.Client, use
return nil
}

func (p *Plugin) SubscribeOrg(ctx context.Context, githubClient *github.Client, userID, org, channelID, features string, flags SubscriptionFlags) error {
func (p *Plugin) SubscribeOrg(ctx context.Context, githubClient *github.Client, userID, org, channelID string, features Features, flags SubscriptionFlags) error {
if org == "" {
return errors.New("invalid organization")
}
Expand Down Expand Up @@ -313,17 +313,7 @@ func (p *Plugin) GetSubscribedChannelsForRepository(repo *github.Repository) []*
return subsToReturn
}

func (p *Plugin) Unsubscribe(channelID string, repo string) error {
config := p.getConfiguration()

owner, repo := parseOwnerAndRepo(repo, config.getBaseURL())
if owner == "" && repo == "" {
return errors.New("invalid repository")
}

owner = strings.ToLower(owner)
repo = strings.ToLower(repo)

func (p *Plugin) Unsubscribe(channelID, repo, owner string) error {
repoWithOwner := fmt.Sprintf("%s/%s", owner, repo)

subs, err := p.GetSubscriptions()
Expand Down