func cacheNickMap(c *integram.Context) error { me, err := me(c) if err != nil { return err } c.SetServiceCache("nick_map_"+me.Username, c.User.UserName, time.Hour*24*365) err = c.SetServiceCache("nick_map_"+me.Email, c.User.UserName, time.Hour*24*365) return err }
func webhookHandler(c *integram.Context, wc *integram.WebhookContext) (err error) { eventKey := wc.Header("X-Event-Key") if eventKey == "" { // try the old one Bitbucket POST service return oldWebhookHandler(c, wc) } if _, ok := eventTypeMap[eventKey]; !ok { return errors.New("Bad X-Event-Key: " + eventKey) } c.Log().Debugf("eventKey=%v", eventKey) if err != nil { return errors.New("JSON deserialization error: " + err.Error()) } switch eventKey { case "repo:push": event := api.RepoPushEvent{} wc.JSON(&event) for _, change := range event.Push.Changes { msg := c.NewMessage() commits := 0 text := "" if len(change.Commits) > 1 { anyOherPersonCommits := false for _, commit := range change.Commits { if commit.Author.User.UUID != event.Actor.UUID { anyOherPersonCommits = true break } } for _, commit := range change.Commits { commits++ if anyOherPersonCommits { text += mention(c, &commit.Author.User) + ": " } text += m.URL(commit.Message, commit.Links.HTML.Href) + "\n" } if change.Truncated { text += m.URL("... See all", change.Links.Commits.Href) + "\n" } } else if len(change.Commits) == 1 { commits++ commit := &change.Commits[0] if commit.Author.User.UUID != event.Actor.UUID { text += mention(c, &commit.Author.User) + ": " } text += commit.Message + "\n" } change.New.Target.Author.User.Links.Avatar.Href = strings.Replace(change.New.Target.Author.User.Links.Avatar.Href, "/32/", "/128/", 1) wp := "" if change.Truncated { wp = c.WebPreview("> 5 commits", "@"+commitShort(change.Old.Target.Hash)+" ... @"+commitShort(change.New.Target.Hash), "", change.Links.HTML.Href, change.New.Target.Author.User.Links.Avatar.Href) } else if commits > 1 { wp = c.WebPreview(fmt.Sprintf("%d commits", commits), "@"+commitShort(change.Old.Target.Hash)+" ... @"+commitShort(change.New.Target.Hash), "", change.Links.HTML.Href, change.New.Target.Author.User.Links.Avatar.Href) } else if commits == 1 { wp = c.WebPreview("Commit", "@"+commitShort(change.New.Target.Hash), "", change.Commits[0].Links.HTML.Href, change.New.Target.Author.User.Links.Avatar.Href) } if commits > 0 { pushedText := "" if change.Forced { pushedText = m.URL("❗️ forcibly pushed", wp) } else { pushedText = m.URL("pushed", wp) } err = msg.SetTextFmt("%s %s to %s/%s\n%s", mention(c, &change.New.Target.Author.User), pushedText, m.URL(event.Repository.Name, event.Repository.Links.HTML.Href), m.URL(change.New.Name, change.New.Links.HTML.Href), text). AddEventID(commitUniqueID(change.Commits[0].Hash)). EnableHTML(). Send() } } case "issue:created": event := api.IssueCreatedEvent{} err := wc.JSON(&event) if err != nil { return err } event.Issue.Repository = &event.Repository c.SetServiceCache(issueUniqueID(event.Repository.FullName, event.Issue.ID), event.Issue, time.Hour*24*365) return c.NewMessage().AddEventID(issueUniqueID(event.Repository.FullName, event.Issue.ID)). SetInlineKeyboard(issueInlineKeyboard(&event.Issue)). SetText(issueText(c, &event.Issue)). SetCallbackAction(issueInlineButtonPressed, event.Repository.FullName, event.Issue.ID). EnableHTML().Send() case "issue:comment_created": event := api.IssueCommentCreatedEvent{} err := wc.JSON(&event) if err != nil { return err } var rm *integram.Message if event.Comment.Parent.ID > 0 { // actually bitbucket doesn't provide parent id for issue comments for now rm, _ = c.FindMessageByEventID(issueCommentUniqueID(event.Repository.FullName, event.Issue.ID, event.Comment.Parent.ID)) } if rm == nil { rm, _ = c.FindMessageByEventID(issueUniqueID(event.Repository.FullName, event.Issue.ID)) } msg := c.NewMessage().AddEventID(issueCommentUniqueID(event.Repository.FullName, event.Issue.ID, event.Comment.ID)).EnableHTML() if rm != nil { return msg.SetReplyToMsgID(rm.MsgID).SetText(fmt.Sprintf("%s: %s", mention(c, &event.Actor), event.Comment.Content.Raw)).Send() } wp := c.WebPreview("Issue", event.Issue.Title, event.Repository.FullName, event.Comment.Links.HTML.Href, "") return msg.SetText(fmt.Sprintf("%s %s: %s", m.URL("💬", wp), mention(c, &event.Actor), event.Comment.Content.Raw)).Send() case "repo:commit_comment_created": event := api.RepoCommitCommentCreatedEvent{} err := wc.JSON(&event) if err != nil { return err } var rm *integram.Message if event.Comment.Parent.ID > 0 { // actually bitbucket doesn't provide parent id for issue comments for now rm, _ = c.FindMessageByEventID(commitCommentUniqueID(event.Commit.Hash, event.Comment.Parent.ID)) } if rm == nil { rm, _ = c.FindMessageByEventID(commitUniqueID(event.Commit.Hash)) } msg := c.NewMessage().AddEventID(commitCommentUniqueID(event.Commit.Hash, event.Comment.Parent.ID)).EnableHTML() if rm != nil { return msg.SetReplyToMsgID(rm.MsgID).SetText(fmt.Sprintf("%s: %s", mention(c, &event.Actor), event.Comment.Content.Raw)).Send() } wp := c.WebPreview("Commit", "@"+event.Commit.Hash[0:10], event.Repository.FullName, event.Comment.Links.HTML.Href, "") return msg.SetText(fmt.Sprintf("%s %s: %s", m.URL("💬", wp), mention(c, &event.Actor), event.Comment.Content.Raw)).Send() case "issue:updated": event := api.IssueUpdatedEvent{} err := wc.JSON(&event) if err != nil { return err } eventID := issueUniqueID(event.Repository.FullName, event.Issue.ID) rm, _ := c.FindMessageByEventID(eventID) msg := c.NewMessage().AddEventID(issueCommentUniqueID(event.Repository.FullName, event.Issue.ID, event.Comment.ID)).EnableHTML() if event.Comment.Content.Raw != "" { event.Comment.Content.Raw = ": " + event.Comment.Content.Raw } if rm != nil { c.EditMessagesTextWithEventID(eventID, issueText(c, &event.Issue)) // if last Issue message just posted if err == nil && time.Now().Sub(rm.Date).Seconds() < 60 { return nil } return msg.SetReplyToMsgID(rm.MsgID).SetText(fmt.Sprintf("%s update the issue%s", mention(c, &event.Actor), event.Comment.Content.Raw)).Send() } return msg.SetText(fmt.Sprintf("%s updated an issue%s\n%s", mention(c, &event.Actor), event.Comment.Content.Raw, issueText(c, &event.Issue))).Send() case "pullrequest:updated": event := api.PullRequestCreatedEvent{} err := wc.JSON(&event) if err != nil { return err } prText := prText(c, &event.PullRequest) eventID := prUniqueID(event.Repository.FullName, event.PullRequest.ID) rm, _ := c.FindMessageByEventID(eventID) msg := c.NewMessage() if rm != nil { c.EditMessagesTextWithEventID(eventID, prText) // if last PR message just posted if err == nil && time.Now().Sub(rm.Date).Seconds() < 60 { return nil } msg.SetReplyToMsgID(rm.MsgID) } else { msg.AddEventID(prUniqueID(event.Repository.FullName, event.PullRequest.ID)) } return msg. SetText("✏️ " + prText). EnableHTML().Send() case "pullrequest:created": event := api.PullRequestCreatedEvent{} err := wc.JSON(&event) if err != nil { return err } c.SetServiceCache(prUniqueID(event.Repository.FullName, event.PullRequest.ID), event.PullRequest, time.Hour*24*365) return c.NewMessage().AddEventID(prUniqueID(event.Repository.FullName, event.PullRequest.ID)). SetText(prText(c, &event.PullRequest)). EnableHTML().Send() case "pullrequest:approved": event := api.PullRequestApprovedEvent{} err := wc.JSON(&event) if err != nil { return err } rm, _ := c.FindMessageByEventID(prUniqueID(event.Repository.FullName, event.PullRequest.ID)) msg := c.NewMessage().EnableHTML() if rm != nil { return msg.SetReplyToMsgID(rm.MsgID).SetText(fmt.Sprintf("✅ Approved by %s", mention(c, &event.Actor))).Send() } wp := c.WebPreview("Pull Request", event.PullRequest.Title, "by "+event.PullRequest.Author.DisplayName+" in "+event.Repository.FullName, event.PullRequest.Links.HTML.Href, "") return msg.SetText(fmt.Sprintf("✅ %s by %s", m.URL("Approved", wp), mention(c, &event.Actor))).Send() case "pullrequest:unapproved": event := api.PullRequestApprovalRemovedEvent{} err := wc.JSON(&event) if err != nil { return err } rm, _ := c.FindMessageByEventID(prUniqueID(event.Repository.FullName, event.PullRequest.ID)) msg := c.NewMessage().EnableHTML() if rm != nil { return msg.SetReplyToMsgID(rm.MsgID).SetText(fmt.Sprintf("❌ %s removed approval", mention(c, &event.Actor))).Send() } wp := c.WebPreview("Pull Request", event.PullRequest.Title, "by "+event.PullRequest.Author.DisplayName+" in "+event.Repository.FullName, event.PullRequest.Links.HTML.Href, "") return msg.SetText(fmt.Sprintf("❌ %s %s", mention(c, &event.Actor), m.URL("removed approval", wp))).Send() case "pullrequest:fulfilled": event := api.PullRequestMergedEvent{} err := wc.JSON(&event) if err != nil { return err } rm, _ := c.FindMessageByEventID(prUniqueID(event.Repository.FullName, event.PullRequest.ID)) msg := c.NewMessage().EnableHTML() if rm != nil { return msg.SetReplyToMsgID(rm.MsgID).SetText(fmt.Sprintf("✅ Merged by %s", mention(c, &event.Actor))).Send() } wp := c.WebPreview("Pull Request", event.PullRequest.Title, "by "+event.PullRequest.Author.DisplayName+" in "+event.Repository.FullName, event.PullRequest.Links.HTML.Href, "") return msg.SetText(fmt.Sprintf("✅ %s by %s", m.URL("Merged", wp), mention(c, &event.Actor))).Send() case "pullrequest:rejected": event := api.PullRequestDeclinedEvent{} err := wc.JSON(&event) if err != nil { return err } rm, _ := c.FindMessageByEventID(prUniqueID(event.Repository.FullName, event.PullRequest.ID)) msg := c.NewMessage().EnableHTML() if rm != nil { return msg.SetReplyToMsgID(rm.MsgID).SetText(fmt.Sprintf("❌ Declined by %s: %s", mention(c, &event.Actor), event.PullRequest.Reason)).Send() } wp := c.WebPreview("Pull Request", event.PullRequest.Title, "by "+event.PullRequest.Author.DisplayName+" in "+event.Repository.FullName, event.PullRequest.Links.HTML.Href, "") return msg.SetText(fmt.Sprintf("❌ %s by %s", m.URL("Declined", wp), mention(c, &event.Actor))).Send() case "pullrequest:comment_created": event := api.PullRequestCommentCreatedEvent{} err := wc.JSON(&event) if err != nil { return err } rm, _ := c.FindMessageByEventID(prUniqueID(event.Repository.FullName, event.PullRequest.ID)) msg := c.NewMessage().AddEventID(prCommentUniqueID(event.Repository.FullName, event.PullRequest.ID, event.Comment.ID)).EnableHTML() if rm != nil { return msg.SetReplyToMsgID(rm.MsgID).SetText(fmt.Sprintf("%s: %s", mention(c, &event.Actor), event.Comment.Content.Raw)).Send() } wp := c.WebPreview("Pull Request", event.PullRequest.Title, event.Repository.FullName, event.PullRequest.Links.HTML.Href, "") return msg.SetText(fmt.Sprintf("%s %s: %s", m.URL("💬", wp), mention(c, &event.Actor), event.Comment.Content.Raw)).Send() } return err }
func storeIssue(c *integram.Context, issue *api.Issue) error { return c.SetServiceCache(issueUniqueID(issue.Repository.FullName, issue.ID), &issue, time.Hour*24*365) }