func commitsReplied(c *integram.Context, baseURL string, projectID int, commits []commit) error { authorized, err := mustBeAuthed(c) if err != nil { return err } if !authorized { //todo:bug message lost return c.User.SetAfterAuthAction(commitsReplied, baseURL, projectID, commits) } buttons := integram.Buttons{} for _, commit := range commits { buttons.Append(commit.ID, trim(commit.Message, 40)) } return c.NewMessage(). SetText(c.User.Mention()+" please specify commit to comment"). SetKeyboard(buttons.Markup(1), true). EnableForceReply(). SetReplyAction(commitToReplySelected, baseURL, projectID, c.Message). Send() }
func prText(c *integram.Context, pr *api.PullRequest) string { r := reRepoFullNameFromURL.FindStringSubmatch(pr.Links.Self.Href) repo := "" if len(r) == 2 { repo = r[1] } if pr.Description == pr.Title { pr.Description = "" } text := fmt.Sprintf("%s %s\n%s", m.Bold(pr.Title), m.URL("➔", c.WebPreview("Pull Request", repo, "by "+pr.Author.DisplayName, pr.Links.HTML.String(), "")), pr.Description) if len(pr.Reviewers) > 0 { text += "\n 👤 " for i, reviewer := range pr.Reviewers { text += mention(c, &reviewer) if i < len(pr.Reviewers)-1 { text += ", " } } } return text }
func mention(c *integram.Context, member *api.Actor) string { userName := "" c.ServiceCache("nick_map_"+member.UUID, &userName) if userName == "" { return m.Bold(member.DisplayName) } return "@" + userName }
func sendSnippetComment(c *integram.Context, projectID int, SnippetID int, text string) error { note, _, err := client(c).Notes.CreateSnippetNote(projectID, SnippetID, &api.CreateSnippetNoteOptions{Body: text}) if note != nil { c.Message.UpdateEventsID(c.Db(), noteUniqueID(projectID, strconv.Itoa(note.ID))) } return err }
func snippetMessageID(c *integram.Context, snippetID int) int { msg, err := c.FindMessageByEventID("snippet_" + strconv.Itoa(snippetID)) if err == nil && msg != nil { return msg.MsgID } return 0 }
func issueMessageID(c *integram.Context, issueID int) int { msg, err := c.FindMessageByEventID("issue_" + strconv.Itoa(issueID)) if err == nil && msg != nil { return msg.MsgID } return 0 }
func commitMessageID(c *integram.Context, commitID string) int { msg, err := c.FindMessageByEventID("commit_" + commitID) if err == nil && msg != nil { return msg.MsgID } return 0 }
func mrMessageID(c *integram.Context, mergeRequestID int) int { msg, err := c.FindMessageByEventID("mr_" + strconv.Itoa(mergeRequestID)) if err == nil && msg != nil { return msg.MsgID } return 0 }
func settings(c *integram.Context) error { btns := integram.InlineButtons{} btns.Append("ci", "CI") btns.Append("mr", "Merge requests") return c.NewMessage().SetText("Tune the notifications").SetInlineKeyboard(btns.Markup(1, "categories")).SetCallbackAction(settingsKeyboardPressed).Send() }
func sendIssueComment(c *integram.Context, projectID int, issueID int, text string) error { note, _, err := client(c).Notes.CreateIssueNote(projectID, issueID, &api.CreateIssueNoteOptions{Body: text}) if note != nil { c.Message.UpdateEventsID(c.Db(), "issue_note_"+strconv.Itoa(note.ID)) } return err }
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 sendCommitComment(c *integram.Context, projectID int, commitID string, msg *integram.IncomingMessage) error { note, _, err := client(c).Notes.CreateCommitNote(projectID, commitID, &api.CreateCommitNoteOptions{Note: msg.Text}) if err != nil { return err } // note id not available for commit comment. So use the date. Collisions are unlikely here... c.Message.UpdateEventsID(c.Db(), noteUniqueID(projectID, note.CreatedAt)) return err }
func commitReplied(c *integram.Context, baseURL string, projectID int, commitID string) error { c.Message.SetReplyAction(commitReplied, baseURL, projectID, commitID) c.SetServiceBaseURL(baseURL) authorized, err := mustBeAuthed(c) if !authorized { return c.User.SetAfterAuthAction(sendCommitComment, c, projectID, commitID, c.Message) } c.Service().DoJob(sendCommitComment, c, projectID, commitID, c.Message) return err }
func mention(c *integram.Context, name string, email string) string { userName := "" c.ServiceCache("nick_map_"+name, &userName) if userName == "" && email != "" { c.ServiceCache("nick_map_"+email, &userName) } if userName == "" { return m.Bold(name) } return "@" + userName }
func settingsKeyboardPressed(c *integram.Context) error { cs := chatSettings(c) state := c.Callback.Message.InlineKeyboardMarkup.State if state == "categories" { state = c.Callback.Data } btns := integram.InlineButtons{} if c.Callback.Data == "back" { btns.Append("ci", "CI") btns.Append("mr", "Merge requests") state = "categories" } else if state == "mr" { btns.Append("back", "← Back") switch c.Callback.Data { case "open": cs.MR.Open = !stateToBool(c.Callback.State) case "close": cs.MR.Close = !stateToBool(c.Callback.State) case "update": cs.MR.Update = !stateToBool(c.Callback.State) case "merge": cs.MR.Merge = !stateToBool(c.Callback.State) } c.Chat.SaveSettings(cs) btns.AppendWithState(boolToState(cs.MR.Open), "open", boolToMark(cs.MR.Open)+"Open") btns.AppendWithState(boolToState(cs.MR.Update), "update", boolToMark(cs.MR.Update)+"Update") btns.AppendWithState(boolToState(cs.MR.Merge), "merge", boolToMark(cs.MR.Merge)+"Merge") btns.AppendWithState(boolToState(cs.MR.Close), "close", boolToMark(cs.MR.Close)+"Close") } else if state == "ci" { btns.Append("back", "← Back") switch c.Callback.Data { case "success": cs.CI.Success = !stateToBool(c.Callback.State) case "fail": cs.CI.Fail = !stateToBool(c.Callback.State) case "cancel": cs.CI.Cancel = !stateToBool(c.Callback.State) } c.Chat.SaveSettings(cs) btns.AppendWithState(boolToState(cs.CI.Success), "success", boolToMark(cs.CI.Success)+"Success") btns.AppendWithState(boolToState(cs.CI.Fail), "fail", boolToMark(cs.CI.Fail)+"Fail") btns.AppendWithState(boolToState(cs.CI.Cancel), "cancel", boolToMark(cs.CI.Cancel)+"Cancel") } return c.EditPressedInlineKeyboard(btns.Markup(1, state)) }
func snippetReplied(c *integram.Context, baseURL string, projectID int, snippetID int) error { c.SetServiceBaseURL(baseURL) authorized, err := mustBeAuthed(c) if !authorized { c.User.SetAfterAuthAction(sendSnippetComment, baseURL, projectID, snippetID, c.Message.Text) } else { _, err = c.Service().DoJob(sendSnippetComment, c, baseURL, projectID, snippetID, c.Message.Text) } c.Message.SetReplyAction(mrReplied, baseURL, projectID, snippetID) return err }
/*func me(c *integram.Context) (*gitlab.User, error) { api:=Api(c).Repositories.Commits.GetCommit() user := &gitlab.User{} c.User.Cache("me", user) if user.ID > 0 { return user, nil } user, _, err := Api(c).Users.CurrentUser() if err != nil { return nil, err } c.User.SetCache("me", user, time.Hour*24*30) return user, nil } 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 hostedAppSecretEntered(c *integram.Context, baseURL string, appID string) error { c.SetServiceBaseURL(baseURL) appSecret := strings.TrimSpace(c.Message.Text) if len(appSecret) != 64 { c.NewMessage().SetText("Looks like this *Application Secret* is incorrect. Must be a 64 HEX symbols. Please try again").EnableHTML().DisableWebPreview().SetReplyAction(hostedAppSecretEntered, baseURL).Send() return errors.New("Application Secret '" + appSecret + "' is incorrect") } conf := integram.OAuthProvider{BaseURL: c.ServiceBaseURL, ID: appID, Secret: appSecret} token, err := conf.OAuth2Client(c).Exchange(oauth2.NoContext, "-") if strings.Contains(err.Error(), `"error":"invalid_grant"`) { // means the app is exists c.SaveOAuthProvider(c.ServiceBaseURL, appID, appSecret) _, err := mustBeAuthed(c) return err } c.NewMessage().SetText("Application ID or Secret is incorrect. Please try again. Enter *Application Id*"). EnableHTML(). SetReplyAction(hostedAppIDEntered, baseURL).Send() fmt.Printf("Exchange: token: %+v, err:%v\n", token, err) return nil }
func issueText(c *integram.Context, issue *api.Issue) string { r := reRepoFullNameFromURL.FindStringSubmatch(issue.Links.Self.Href) repo := "" if len(r) == 2 { repo = r[1] } return fmt.Sprintf("%s %s\n%s\n%s", m.Bold(issue.Title), m.URL("➔", c.WebPreview("by "+issue.Reporter.DisplayName, repo, "", issue.Links.HTML.String(), "")), issue.Content.Raw, "#"+issue.Priority+" #"+issue.Type) }
func prInlineButtonPressed(c *integram.Context, fullRepoName string, prID int) error { if ok, err := mustBeAuthed(c); !ok { return err } pr := api.PullRequest{} c.ServiceCache(issueUniqueID(fullRepoName, prID), &pr) switch c.Callback.Data { case "back": return c.EditPressedInlineKeyboard(prInlineKeyboard(&pr)) case "assign": //rest.Repositories.ListPublic() } return nil }
func update(c *integram.Context) error { command, param := c.Message.GetCommand() if c.Message.IsEventBotAddedToGroup() { command = "start" } if param == "silent" { command = "" } switch command { case "start": return c.NewMessage().EnableAntiFlood().EnableHTML(). SetText("Hi here! You can send " + m.URL("Slack-compatible", "https://api.slack.com/docs/message-formatting#message_formatting") + " simple webhooks to " + m.Bold("this chat") + " using this URL: \n" + m.Fixed(c.Chat.ServiceHookURL()) + "\n\nExample (JSON payload):\n" + m.Pre("{\"text\":\"So _advanced_\\nMuch *innovations* 🙀\"}")).Send() } return nil }
func webhookHandler(c *integram.Context, wc *integram.WebhookContext) (err error) { wh := webhook{Mrkdwn: true} err = wc.JSON(&wh) if err != nil { return } if len(wh.Attachments) > 0 { if wh.Text != "" { wh.Text += "\n" } wp := c.WebPreview(wh.Attachments[0].Title, wh.Attachments[0].AuthorName, wh.Attachments[0].Pretext, wh.Attachments[0].TitleLink, wh.Attachments[0].ThumbURL) text := m.URL(" ", wp) + " " + wh.Text for i, attachment := range wh.Attachments { if i > 0 { text += "\n" } text += m.URL(attachment.Title, attachment.TitleLink) + " " + attachment.Pretext } return c.NewMessage().SetText(text).EnableAntiFlood().EnableHTML().Send() } if wh.Text != "" { m := c.NewMessage().SetText(wh.Text + " " + wh.Channel).EnableAntiFlood() if wh.Mrkdwn { m.EnableMarkdown() } return m.Send() } return errors.New("Text and Attachments not found") }
func update(c *integram.Context) error { command, param := c.Message.GetCommand() if c.Message.IsEventBotAddedToGroup() { command = "start" } if param == "silent" { command = "" } switch command { case "start": return c.NewMessage().EnableAntiFlood().EnableHTML(). SetTextFmt("Hi here! To setup notifications for %s for your BitBucket repo, open Settings -> Webhooks and add this URL:\n%s\n%s", m.Bold("this chat"), m.Fixed(c.Chat.ServiceHookURL()), m.Bold("⚠️ Don't forget to add all triggers inside the \"Choose from a full list of triggers\" radio button!")).Send() case "cancel", "clean", "reset": return c.NewMessage().SetText("Clean").HideKeyboard().Send() } return nil }
func update(c *integram.Context) error { command, param := c.Message.GetCommand() if c.Message.IsEventBotAddedToGroup() { command = "start" } if param == "silent" { command = "" } switch command { case "start": return c.NewMessage().EnableAntiFlood().EnableHTML(). SetText("Hi here! To setup notifications " + m.Bold("for this chat") + " your GitLab project(repo), open Settings -> Web Hooks and add this URL:\n" + m.Fixed(c.Chat.ServiceHookURL())).EnableHTML().Send() case "cancel", "clean", "reset": return c.NewMessage().SetText("Clean").HideKeyboard().Send() case "settings": return settings(c) } return nil }
func hostedAppIDEntered(c *integram.Context, baseURL string) error { c.SetServiceBaseURL(baseURL) appID := strings.TrimSpace(c.Message.Text) if len(appID) != 64 { c.NewMessage().SetText("Looks like this *Application Id* is incorrect. Must be a 64 HEX symbols. Please try again"). EnableHTML(). SetReplyAction(hostedAppIDEntered, baseURL).Send() return errors.New("Application Id '" + appID + "' is incorrect") } return c.NewMessage().SetText("Great! Now write me the *Secret* for this application"). EnableHTML(). SetReplyAction(hostedAppSecretEntered, baseURL, appID).Send() }
// we nee msg param because action c.Message can contains selected commit id from prev state at commitsReplied and not the comment message func commitToReplySelected(c *integram.Context, baseURL string, projectID int, msg *integram.IncomingMessage) error { commitID, _ := c.KeyboardAnswer() c.Message.SetReplyAction(commitReplied, baseURL, projectID, commitID) c.SetServiceBaseURL(baseURL) authorized, err := mustBeAuthed(c) if !authorized { return c.User.SetAfterAuthAction(sendCommitComment, c, projectID, commitID, msg.Text) } c.Service().DoJob(sendCommitComment, projectID, commitID) return err }
func mustBeAuthed(c *integram.Context) (bool, error) { provider := c.OAuthProvider() if !provider.IsSetup() { return false, c.NewMessage().SetText(fmt.Sprintf("To be able to use interactive replies in Telegram, first you need to add oauth application on your hosted GitLab instance (admin priveleges required): %s\nAdd application with any name(f.e. Telegram) and specify this *Redirect URI*: \n%s\n\nAfter you press *Submit* you will receive app info. First, send me the *Application ID*", c.ServiceBaseURL.String()+"/admin/applications/new", provider.RedirectURL())). SetChat(c.User.ID). SetBackupChat(c.Chat.ID). EnableHTML(). EnableForceReply(). DisableWebPreview(). SetReplyAction(hostedAppIDEntered, c.ServiceBaseURL.String()).Send() } if !c.User.OAuthValid() { return false, c.NewMessage().SetTextFmt("You need to authorize me to use interactive replies: %s", c.User.OauthInitURL()). DisableWebPreview(). SetChat(c.User.ID).SetBackupChat(c.Chat.ID).Send() } return true, nil }
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 oldWebhookHandler(c *integram.Context, wc *integram.WebhookContext) (err error) { wh := oldWebhook{} payload := wc.FormValue("payload") if payload == "" { return errors.New("X-Event-Key header missed and old-style webhook data not found") } json.Unmarshal([]byte(payload), &wh) if wh.CanonURL == "" { return errors.New("Error decoding payload for old webhook") } msg := c.NewMessage() commits := 0 text := "" wp := "" if len(wh.Commits) == 0 { return nil } headCommit := wh.Commits[len(wh.Commits)-1] if len(wh.Commits) > 1 { wp = c.WebPreview(fmt.Sprintf("%d commits", len(wh.Commits)), "@"+wh.Commits[0].Node[0:10]+" ... @"+headCommit.Node[0:10], "", wh.CanonURL+wh.Repository.AbsoluteURL+"/compare/"+headCommit.Node+".."+wh.Commits[0].Parents[0], "") anyOherPersonCommits := false for _, commit := range wh.Commits { if commit.Author != wh.User { anyOherPersonCommits = true break } } for _, commit := range wh.Commits { commits++ if anyOherPersonCommits { text += m.Bold(commit.Author) + ": " } text += m.URL(commit.Message, wh.CanonURL+wh.Repository.AbsoluteURL+"commits/"+headCommit.Node[0:10]) + "\n" } } else if len(wh.Commits) == 1 { wp = c.WebPreview("Commit", "@"+headCommit.Node[0:10], "", wh.CanonURL+wh.Repository.AbsoluteURL+"commits/"+headCommit.Node[0:10], "") commit := &wh.Commits[0] if commit.Author != wh.User { text += m.Bold(commit.Author) + ": " } text += commit.Message + "\n" } if len(wh.Commits) > 0 { return msg.SetTextFmt("%s %s to %s/%s\n%s", m.Bold(wh.User), m.URL("pushed", wp), m.URL(wh.Repository.Name, wh.CanonURL+wh.Repository.AbsoluteURL), m.URL(headCommit.Branch, wh.CanonURL+wh.Repository.AbsoluteURL+"branch/"+headCommit.Branch), text). EnableHTML(). Send() } return nil }
func mustBeAuthed(c *integram.Context) (bool, error) { provider := c.OAuthProvider() if !provider.IsSetup() { return false, c.NewMessage().SetText(fmt.Sprintf("To be able to use interactive replies in Telegram, first you need to add oauth application on your hosted Bitbucket instance (admin priveleges required): %s\nAdd application with any name(f.e. Telegram) and specify this *Redirect URI*: \n%s\n\nAfter you press *Submit* you will receive app info. First, send me the *Application Id*", c.ServiceBaseURL.String()+"/account/", provider.RedirectURL())). SetChat(c.User.ID). SetBackupChat(c.Chat.ID). EnableHTML(). EnableForceReply(). DisableWebPreview(). SetReplyAction(hostedAppIDEntered, c.ServiceBaseURL.String()).Send() } if !c.User.OAuthValid() { if c.Callback != nil { c.AnswerCallbackQuery("You need to authorize me\nUse the \"Tap me to auth\" button", true) } if !c.User.IsPrivateStarted() && c.Callback != nil { kb := c.Callback.Message.InlineKeyboardMarkup kb.AddPMSwitchButton(c.Bot(), "👉 Tap me to auth", "auth") c.EditPressedInlineKeyboard(kb) } else { return false, c.NewMessage().SetTextFmt("You need to authorize me to use interactive replies: %s", c.User.OauthInitURL()). DisableWebPreview(). SetChat(c.User.ID).SetBackupChat(c.Chat.ID).Send() } } return true, nil }
func oAuthSuccessful(c *integram.Context) error { return c.NewMessage().SetText("Great! Now you can reply issues, commits, merge requests and snippets").Send() }