Skip to content

Commit

Permalink
[GH-500]: Fixed github issue "Emoji synchronisation for PR/issue on g…
Browse files Browse the repository at this point in the history
…ithub" (#632)
  • Loading branch information
Kshitij-Katiyar authored Feb 23, 2023
1 parent 756311d commit 8d28b2e
Show file tree
Hide file tree
Showing 2 changed files with 217 additions and 0 deletions.
181 changes: 181 additions & 0 deletions server/plugin/plugin.go
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,8 @@ type Plugin struct {

webhookBroker *WebhookBroker
oauthBroker *OAuthBroker

emojiMap map[string]string
}

// NewPlugin returns an instance of a Plugin.
Expand All @@ -111,9 +113,34 @@ func NewPlugin() *Plugin {
"issue": p.handleIssue,
}

p.createGithubEmojiMap()
return p
}

func (p *Plugin) createGithubEmojiMap() {
baseGithubEmojiMap := map[string]string{
"+1": "+1",
"-1": "-1",
"thumbsup": "+1",
"thumbsdown": "-1",
"laughing": "laugh",
"confused": "confused",
"heart": "heart",
"tada": "hooray",
"rocket": "rocket",
"eyes": "eyes",
}

p.emojiMap = map[string]string{}
for systemEmoji := range model.SystemEmojis {
for mmBase, ghBase := range baseGithubEmojiMap {
if strings.HasPrefix(systemEmoji, mmBase) {
p.emojiMap[systemEmoji] = ghBase
}
}
}
}

func (p *Plugin) GetGitHubClient(ctx context.Context, userID string) (*github.Client, error) {
userInfo, apiErr := p.getGitHubUserInfo(userID)
if apiErr != nil {
Expand Down Expand Up @@ -251,6 +278,160 @@ func (p *Plugin) OnDeactivate() error {
return nil
}

func (p *Plugin) getPostPropsForReaction(reaction *model.Reaction) (org, repo string, id float64, objectType string, ok bool) {
post, err := p.client.Post.GetPost(reaction.PostId)
if err != nil {
p.API.LogDebug("Error fetching post for reaction", "error", err.Error())
return org, repo, id, objectType, false
}

// Getting the Github repository from notification post props
repo, ok = post.GetProp(postPropGithubRepo).(string)
if !ok || repo == "" {
return org, repo, id, objectType, false
}

orgRepo := strings.Split(repo, "/")
if len(orgRepo) != 2 {
p.API.LogDebug("Invalid organization repository")
return org, repo, id, objectType, false
}

org, repo = orgRepo[0], orgRepo[1]

// Getting the Github object id from notification post props
id, ok = post.GetProp(postPropGithubObjectID).(float64)
if !ok || id == 0 {
return org, repo, id, objectType, false
}

// Getting the Github object type from notification post props
objectType, ok = post.GetProp(postPropGithubObjectType).(string)
if !ok || objectType == "" {
return org, repo, id, objectType, false
}

return org, repo, id, objectType, true
}

func (p *Plugin) ReactionHasBeenAdded(c *plugin.Context, reaction *model.Reaction) {
githubEmoji := p.emojiMap[reaction.EmojiName]
if githubEmoji == "" {
p.API.LogWarn("Emoji is not supported by Github", "Emoji", reaction.EmojiName)
return
}

owner, repo, id, objectType, ok := p.getPostPropsForReaction(reaction)
if !ok {
return
}

info, appErr := p.getGitHubUserInfo(reaction.UserId)
if appErr != nil {
if appErr.ID != apiErrorIDNotConnected {
p.API.LogDebug("Error in getting user info", "error", appErr.Error())
}
return
}

ctx, cancel := context.WithTimeout(context.Background(), requestTimeout)
defer cancel()
ghClient := p.githubConnectUser(ctx, info)
switch objectType {
case githubObjectTypeIssueComment:
if _, _, err := ghClient.Reactions.CreateIssueCommentReaction(context.Background(), owner, repo, int64(id), githubEmoji); err != nil {
p.API.LogDebug("Error occurred while creating issue comment reaction", "error", err.Error())
return
}
case githubObjectTypeIssue:
if _, _, err := ghClient.Reactions.CreateIssueReaction(context.Background(), owner, repo, int(id), githubEmoji); err != nil {
p.API.LogDebug("Error occurred while creating issue reaction", "error", err.Error())
return
}
case githubObjectTypePRReviewComment:
if _, _, err := ghClient.Reactions.CreatePullRequestCommentReaction(context.Background(), owner, repo, int64(id), githubEmoji); err != nil {
p.API.LogDebug("Error occurred while creating PR review comment reaction", "error", err.Error())
return
}
default:
return
}
}

func (p *Plugin) ReactionHasBeenRemoved(c *plugin.Context, reaction *model.Reaction) {
githubEmoji := p.emojiMap[reaction.EmojiName]
if githubEmoji == "" {
p.API.LogWarn("Emoji is not supported by Github", "Emoji", reaction.EmojiName)
return
}

owner, repo, id, objectType, ok := p.getPostPropsForReaction(reaction)
if !ok {
return
}

info, appErr := p.getGitHubUserInfo(reaction.UserId)
if appErr != nil {
if appErr.ID != apiErrorIDNotConnected {
p.API.LogDebug("Error in getting user info", "error", appErr.Error())
}
return
}

ctx, cancel := context.WithTimeout(context.Background(), requestTimeout)
defer cancel()
ghClient := p.githubConnectUser(ctx, info)
switch objectType {
case githubObjectTypeIssueComment:
reactions, _, err := ghClient.Reactions.ListIssueCommentReactions(context.Background(), owner, repo, int64(id), &github.ListOptions{})
if err != nil {
p.API.LogDebug("Error getting issue comment reaction list", "error", err.Error())
return
}

for _, reactionObj := range reactions {
if info.UserID == reaction.UserId && p.emojiMap[reaction.EmojiName] == reactionObj.GetContent() {
if _, err = ghClient.Reactions.DeleteIssueCommentReaction(context.Background(), owner, repo, int64(id), reactionObj.GetID()); err != nil {
p.API.LogDebug("Error occurred while removing issue comment reaction", "error", err.Error())
}
return
}
}
case githubObjectTypeIssue:
reactions, _, err := ghClient.Reactions.ListIssueReactions(context.Background(), owner, repo, int(id), &github.ListOptions{})
if err != nil {
p.API.LogDebug("Error getting issue reaction list", "error", err.Error())
return
}

for _, reactionObj := range reactions {
if info.UserID == reaction.UserId && p.emojiMap[reaction.EmojiName] == reactionObj.GetContent() {
if _, err = ghClient.Reactions.DeleteIssueReaction(context.Background(), owner, repo, int(id), reactionObj.GetID()); err != nil {
p.API.LogDebug("Error occurred while removing issue reaction", "error", err.Error())
}
return
}
}
case githubObjectTypePRReviewComment:
reactions, _, err := ghClient.Reactions.ListPullRequestCommentReactions(context.Background(), owner, repo, int64(id), &github.ListOptions{})
if err != nil {
p.API.LogDebug("Error getting PR review comment reaction list", "error", err.Error())
return
}

for _, reactionObj := range reactions {
if info.UserID == reaction.UserId && p.emojiMap[reaction.EmojiName] == reactionObj.GetContent() {
if _, err = ghClient.Reactions.DeletePullRequestCommentReaction(context.Background(), owner, repo, int64(id), reactionObj.GetID()); err != nil {
p.API.LogDebug("Error occurred while removing PR review comment reaction", "error", err.Error())
}
return
}
}
default:
return
}
}

func (p *Plugin) OnInstall(c *plugin.Context, event model.OnInstallEvent) error {
// Don't start wizard if OAuth is configured
if p.getConfiguration().IsOAuthConfigured() {
Expand Down
36 changes: 36 additions & 0 deletions server/plugin/webhook.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,14 @@ const (
actionCreated = "created"
actionDeleted = "deleted"
actionEdited = "edited"

postPropGithubRepo = "gh_repo"
postPropGithubObjectID = "gh_object_id"
postPropGithubObjectType = "gh_object_type"

githubObjectTypeIssue = "issue"
githubObjectTypeIssueComment = "issue_comment"
githubObjectTypePRReviewComment = "pr_review_comment"
)

// RenderConfig holds various configuration options to be used in a template
Expand Down Expand Up @@ -387,6 +395,13 @@ func (p *Plugin) postPullRequestEvent(event *github.PullRequestEvent) {
}
}

repoName := strings.ToLower(repo.GetFullName())
prNumber := event.GetPullRequest().Number

post.AddProp(postPropGithubRepo, repoName)
post.AddProp(postPropGithubObjectID, prNumber)
post.AddProp(postPropGithubObjectType, githubObjectTypeIssue)

if !contained && label != "" {
continue
}
Expand Down Expand Up @@ -555,6 +570,13 @@ func (p *Plugin) postIssueEvent(event *github.IssuesEvent) {
Message: renderedMessage,
}

repoName := strings.ToLower(repo.GetFullName())
issueNumber := issue.Number

post.AddProp(postPropGithubRepo, repoName)
post.AddProp(postPropGithubObjectID, issueNumber)
post.AddProp(postPropGithubObjectType, githubObjectTypeIssue)

label := sub.Label()

contained := false
Expand Down Expand Up @@ -731,6 +753,13 @@ func (p *Plugin) postIssueCommentEvent(event *github.IssueCommentEvent) {
Type: "custom_git_comment",
}

repoName := strings.ToLower(repo.GetFullName())
commentID := event.GetComment().GetID()

post.AddProp(postPropGithubRepo, repoName)
post.AddProp(postPropGithubObjectID, commentID)
post.AddProp(postPropGithubObjectType, githubObjectTypeIssueComment)

labels := make([]string, len(event.GetIssue().Labels))
for i, v := range event.GetIssue().Labels {
labels[i] = v.GetName()
Expand Down Expand Up @@ -864,6 +893,13 @@ func (p *Plugin) postPullRequestReviewCommentEvent(event *github.PullRequestRevi
Message: newReviewMessage,
}

repoName := strings.ToLower(repo.GetFullName())
commentID := event.GetComment().GetID()

post.AddProp(postPropGithubRepo, repoName)
post.AddProp(postPropGithubObjectID, commentID)
post.AddProp(postPropGithubObjectType, githubObjectTypePRReviewComment)

labels := make([]string, len(event.GetPullRequest().Labels))
for i, v := range event.GetPullRequest().Labels {
labels[i] = v.GetName()
Expand Down

0 comments on commit 8d28b2e

Please sign in to comment.